# HG changeset patch # User wetmore # Date 1527799166 25200 # Node ID c10dbcaed048eea0bbc5800e2a5ec3e1b121e22c # Parent d66751750b728ef84dfbfff9d7977ec84769c656# Parent d0d933d616105f3cd482f97658af1826fd4f2c0c Merge diff -r d66751750b72 -r c10dbcaed048 .hgtags --- a/.hgtags Wed May 30 11:36:46 2018 -0700 +++ b/.hgtags Thu May 31 13:39:26 2018 -0700 @@ -487,3 +487,4 @@ 758deedaae8406ae60147486107a54e9864aa7b0 jdk-11+13 3595bd343b65f8c37818ebe6a4c343ddeb1a5f88 jdk-11+14 a11c1cb542bbd1671d25b85efe7d09b983c48525 jdk-11+15 +02934b0d661b82b7fe1052a04998d2091352e08d jdk-11+16 diff -r d66751750b72 -r c10dbcaed048 make/BuildNashorn.gmk --- a/make/BuildNashorn.gmk Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -# -# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# This must be the first rule -default: all - -include $(SPEC) -include MakeBase.gmk -include JarArchive.gmk -include JavaCompilation.gmk -include SetupJavaCompilers.gmk -include TextFileProcessing.gmk -include Modules.gmk - -JDK_CLASSES := $(call PathList, $(strip $(addprefix $(JDK_OUTPUTDIR)/modules/, \ - java.base java.logging java.scripting jdk.dynalink))) - -# Need to use source and target 8 for nasgen to work. -$(eval $(call SetupJavaCompiler, GENERATE_NEWBYTECODE_DEBUG, \ - JVM := $(JAVA_JAVAC), \ - JAVAC := $(NEW_JAVAC), \ - FLAGS := -g -source 10 -target 10 --upgrade-module-path "$(JDK_OUTPUTDIR)/modules/" \ - --system none --module-source-path $(call GetModuleSrcPath), \ - SERVER_DIR := $(SJAVAC_SERVER_DIR), \ - SERVER_JVM := $(SJAVAC_SERVER_JAVA))) - -# Build nashorn into intermediate directory -# Name the compilation setup the same as the module, as is done in the global -# CompileJavaModules.gmk, to make dependency checking with other modules work -# seamlessly. -$(eval $(call SetupJavaCompilation, jdk.scripting.nashorn, \ - SETUP := GENERATE_NEWBYTECODE_DEBUG, \ - MODULE := jdk.scripting.nashorn, \ - SRC := $(TOPDIR)/src/jdk.scripting.nashorn/share/classes, \ - COPY := .properties .js, \ - BIN := $(SUPPORT_OUTPUTDIR)/special_classes, \ - CREATE_API_DIGEST := true, \ -)) - -# Declare dependencies between java compilations of different modules. -# Since the other modules are declared in different invocations of this file, -# use the macro to find the correct target file to depend on. -# Only the javac compilation actually depends on other modules so limit -# dependency declaration to that by using the *_COMPILE_TARGET variable. -$(jdk.scripting.nashorn_COMPILE_TARGET): $(foreach d, $(call FindDepsForModule, jdk.scripting.nashorn), \ - $(call SetupJavaCompilationApiTarget, $d, \ - $(if $($d_BIN), $($d_BIN), $(JDK_OUTPUTDIR)/modules/$d))) - -NASGEN_SRC := $(TOPDIR)/make/nashorn/buildtools/nasgen/src -ASM_SRC := $(TOPDIR)/src/java.base/share/classes/jdk/internal/org/objectweb/asm - -# Build nasgen -$(eval $(call SetupJavaCompilation, BUILD_NASGEN, \ - SETUP := GENERATE_OLDBYTECODE, \ - SRC := $(NASGEN_SRC) $(ASM_SRC), \ - BIN := $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes)) - -NASHORN_CLASSES_DIR := $(JDK_OUTPUTDIR)/modules/jdk.scripting.nashorn -NASGEN_RUN_FILE := $(NASHORN_CLASSES_DIR)/_the.nasgen.run - -NASGEN_OPTIONS := \ - -cp $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \ - --patch-module java.base=$(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \ - --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.org.objectweb.asm.util=ALL-UNNAMED \ - # - -# Copy classes to final classes dir and run nasgen to modify classes in jdk.nashorn.internal.objects package -$(NASGEN_RUN_FILE): $(BUILD_NASGEN) $(jdk.scripting.nashorn) - $(ECHO) Running nasgen - $(MKDIR) -p $(@D) - $(RM) -rf $(@D)/jdk $(@D)/netscape - $(CP) -R -p $(SUPPORT_OUTPUTDIR)/special_classes/jdk.scripting.nashorn/* $(@D)/ - $(JAVA_SMALL) $(NASGEN_OPTIONS) \ - jdk.nashorn.internal.tools.nasgen.Main $(@D) jdk.nashorn.internal.objects $(@D) - $(TOUCH) $@ - -# Version file needs to be processed with version numbers -$(eval $(call SetupTextFileProcessing, BUILD_VERSION_FILE, \ - SOURCE_FILES := $(TOPDIR)/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/version.properties.template, \ - OUTPUT_FILE := $(JDK_OUTPUTDIR)/modules/jdk.scripting.nashorn/jdk/nashorn/internal/runtime/resources/version.properties, \ - REPLACEMENTS := \ - @@VERSION_STRING@@ => $(VERSION_STRING) ; \ - @@VERSION_SHORT@@ => $(VERSION_SHORT) , \ -)) - -# Version processing needs to happen after nasgen run since nasgen run deletes it -$(BUILD_VERSION_FILE): $(NASGEN_RUN_FILE) - -compile: $(NASGEN_RUN_FILE) $(BUILD_VERSION_FILE) -all: compile - -.PHONY: compile all diff -r d66751750b72 -r c10dbcaed048 make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Wed May 30 11:36:46 2018 -0700 +++ b/make/CompileJavaModules.gmk Thu May 31 13:39:26 2018 -0700 @@ -341,6 +341,10 @@ ################################################################################ +jdk.scripting.nashorn_COPY := .properties .js + +################################################################################ + jdk.scripting.nashorn.shell_COPY += .js .properties ################################################################################ @@ -440,11 +444,13 @@ jdk.internal.vm.compiler_EXCLUDES += \ jdk.internal.vm.compiler.collections.test \ + org.graalvm.compiler.processor \ org.graalvm.compiler.core.match.processor \ org.graalvm.compiler.nodeinfo.processor \ org.graalvm.compiler.options.processor \ org.graalvm.compiler.serviceprovider.processor \ - org.graalvm.compiler.replacements.verifier \ + org.graalvm.compiler.replacements.processor \ + org.graalvm.compiler.replacements.jdk9.test \ org.graalvm.compiler.api.directives.test \ org.graalvm.compiler.api.test \ org.graalvm.compiler.asm.aarch64.test \ @@ -642,6 +648,12 @@ ################################################################################ +ifeq ($(MODULE), jdk.scripting.nashorn) + include CompileJavaModulesNashorn.gmk +endif + +################################################################################ + $(eval $(call IncludeCustomExtension, CompileJavaModules-post.gmk)) ################################################################################ diff -r d66751750b72 -r c10dbcaed048 make/CompileJavaModulesNashorn.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/CompileJavaModulesNashorn.gmk Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,54 @@ +# +# Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +NASGEN_SRC := $(TOPDIR)/make/nashorn/buildtools/nasgen/src +ASM_SRC := $(TOPDIR)/src/java.base/share/classes/jdk/internal/org/objectweb/asm + +# Build nasgen +$(eval $(call SetupJavaCompilation, BUILD_NASGEN, \ + SETUP := GENERATE_OLDBYTECODE, \ + SRC := $(NASGEN_SRC) $(ASM_SRC), \ + BIN := $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes, \ +)) + +NASHORN_CLASSES_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE) +NASGEN_RUN_FILE := $(NASHORN_CLASSES_DIR)/_the.nasgen.run + +NASGEN_OPTIONS := \ + -cp $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \ + --patch-module java.base=$(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \ + --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \ + --add-exports java.base/jdk.internal.org.objectweb.asm.util=ALL-UNNAMED \ + # + +# Run nasgen to modify classes in jdk.nashorn.internal.objects package +$(NASGEN_RUN_FILE): $(BUILD_NASGEN) $($(MODULE)) + $(ECHO) Running nasgen + $(JAVA_SMALL) $(NASGEN_OPTIONS) \ + jdk.nashorn.internal.tools.nasgen.Main $(@D) \ + jdk.nashorn.internal.objects $(@D) + $(TOUCH) $@ + +TARGETS += $(NASGEN_RUN_FILE) diff -r d66751750b72 -r c10dbcaed048 make/CompileToolsHotspot.gmk --- a/make/CompileToolsHotspot.gmk Wed May 30 11:36:46 2018 -0700 +++ b/make/CompileToolsHotspot.gmk Thu May 31 13:39:26 2018 -0700 @@ -47,34 +47,8 @@ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/jdk.internal.vm.compiler.word/src \ - $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \ - $(SRC_DIR)/org.graalvm.compiler.core/src \ - $(SRC_DIR)/org.graalvm.compiler.core.common/src \ + $(SRC_DIR)/org.graalvm.compiler.processor/src \ $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \ - $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ - $(SRC_DIR)/org.graalvm.compiler.asm/src \ - $(SRC_DIR)/org.graalvm.compiler.bytecode/src \ - $(SRC_DIR)/org.graalvm.compiler.code/src \ - $(SRC_DIR)/org.graalvm.compiler.debug/src \ - $(SRC_DIR)/org.graalvm.compiler.graph/src \ - $(SRC_DIR)/org.graalvm.compiler.lir/src \ - $(SRC_DIR)/org.graalvm.compiler.loop/src \ - $(SRC_DIR)/org.graalvm.compiler.loop.phases/src \ - $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ - $(SRC_DIR)/org.graalvm.compiler.nodes/src \ - $(SRC_DIR)/org.graalvm.compiler.options/src \ - $(SRC_DIR)/org.graalvm.compiler.phases/src \ - $(SRC_DIR)/org.graalvm.compiler.phases.common/src \ - $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ - $(SRC_DIR)/org.graalvm.compiler.virtual/src \ - $(SRC_DIR)/org.graalvm.graphio/src \ - $(SRC_DIR)/org.graalvm.util/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.runtime/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.services/src \ , \ EXCLUDE_FILES := $(EXCLUDE_FILES), \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.match.processor, \ @@ -88,7 +62,7 @@ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_NODEINFO_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ + $(SRC_DIR)/org.graalvm.compiler.processor/src \ $(SRC_DIR)/org.graalvm.compiler.nodeinfo.processor/src \ , \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.nodeinfo.processor, \ @@ -102,10 +76,8 @@ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_OPTIONS_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \ - $(SRC_DIR)/org.graalvm.compiler.options/src \ + $(SRC_DIR)/org.graalvm.compiler.processor/src \ $(SRC_DIR)/org.graalvm.compiler.options.processor/src \ - $(SRC_DIR)/org.graalvm.util/src \ , \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \ @@ -115,44 +87,26 @@ ############################################################################## - $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \ + $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/jdk.internal.vm.compiler.word/src \ - $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \ - $(SRC_DIR)/org.graalvm.compiler.bytecode/src \ - $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \ - $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ - $(SRC_DIR)/org.graalvm.compiler.code/src \ - $(SRC_DIR)/org.graalvm.compiler.core.common/src \ - $(SRC_DIR)/org.graalvm.compiler.debug/src \ - $(SRC_DIR)/org.graalvm.compiler.graph/src \ - $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ - $(SRC_DIR)/org.graalvm.compiler.options/src \ - $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ - $(SRC_DIR)/org.graalvm.graphio/src \ - $(SRC_DIR)/org.graalvm.util/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.runtime/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.services/src \ + $(SRC_DIR)/org.graalvm.compiler.processor/src \ + $(SRC_DIR)/org.graalvm.compiler.replacements.processor/src \ , \ EXCLUDE_FILES := $(EXCLUDE_FILES), \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.replacements.verifier, \ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.replacements.verifier.jar, \ )) - TARGETS += $(BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER) + TARGETS += $(BUILD_VM_COMPILER_REPLACEMENTS_PROCESSOR) ############################################################################## $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_SERVICEPROVIDER_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ + $(SRC_DIR)/org.graalvm.compiler.processor/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider.processor/src \ - $(VM_CI_SRC_DIR)/jdk.vm.ci.services/src \ , \ EXCLUDE_FILES := $(EXCLUDE_FILES), \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.serviceprovider.processor, \ diff -r d66751750b72 -r c10dbcaed048 make/Main.gmk --- a/make/Main.gmk Wed May 30 11:36:46 2018 -0700 +++ b/make/Main.gmk Thu May 31 13:39:26 2018 -0700 @@ -98,13 +98,10 @@ ################################################################################ # Special targets for certain modules -unpack-sec: - +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f UnpackSecurity.gmk) - generate-exported-symbols: +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f BuildStatic.gmk) -ALL_TARGETS += unpack-sec generate-exported-symbols +ALL_TARGETS += generate-exported-symbols ################################################################################ # Gensrc targets, generating source before java compilation can be done @@ -189,7 +186,7 @@ ALL_TARGETS += $(ALL_COPY_TARGETS) ################################################################################ -# Targets for compiling all java modules. Nashorn is treated separately. +# Targets for compiling all java modules. JAVA_MODULES := $(ALL_MODULES) JAVA_TARGETS := $(addsuffix -java, $(JAVA_MODULES)) @@ -199,14 +196,7 @@ -f CompileJavaModules.gmk MODULE=$1) endef -$(foreach m, $(filter-out jdk.scripting.nashorn, $(JAVA_MODULES)), \ - $(eval $(call DeclareCompileJavaRecipe,$m))) - -# Build nashorn. Needs to be compiled separately from the rest of the modules -# due to nasgen. -jdk.scripting.nashorn-java: - +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) \ - -f BuildNashorn.gmk compile) +$(foreach m, $(JAVA_MODULES), $(eval $(call DeclareCompileJavaRecipe,$m))) ALL_TARGETS += $(JAVA_TARGETS) @@ -700,9 +690,6 @@ # file to be processed by the gensrc-moduleinfo target. jdk.internal.vm.compiler-gensrc-moduleinfo: jdk.internal.vm.compiler-gensrc-src - # Explicitly add dependencies for special targets - java.base-java: unpack-sec - jdk.jdeps-gendata: java rmic # The ct.sym generation uses all the moduleinfos as input diff -r d66751750b72 -r c10dbcaed048 make/UnpackSecurity.gmk --- a/make/UnpackSecurity.gmk Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -# -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -default: all - -include $(SPEC) -include MakeBase.gmk - -################################################################################ -# Unpack the binary distributions of the crypto classes if they exist. -SEC_FILES_ZIP := $(TOPDIR)/make/tools/crypto/sec-bin.zip -SEC_FILES_WIN_ZIP := $(TOPDIR)/make/tools/crypto/sec-windows-bin.zip -JGSS_WIN32_FILES_ZIP := $(TOPDIR)/make/tools/crypto/jgss-windows-i586-bin.zip -JGSS_WIN64_FILES_ZIP := $(TOPDIR)/make/tools/crypto/jgss-windows-x64-bin.zip - -define unzip-sec-file - $(ECHO) Unzipping $( $@.tmp) - $(MV) $@.tmp $@ -endef - -define unzip-native-sec-file - $(ECHO) Unzipping $( $@.tmp) - $(MV) $@.tmp $@ -endef - -$(SUPPORT_OUTPUTDIR)/_the.sec-bin.unzipped: $(SEC_FILES_ZIP) - $(call unzip-sec-file) - -# Trying to unzip both of the sec files at the same time may cause a race -# when creating directories common to both files. -$(SUPPORT_OUTPUTDIR)/_the.sec-windows-bin.unzipped: $(SEC_FILES_WIN_ZIP) \ - | $(SUPPORT_OUTPUTDIR)/_the.sec-bin.unzipped - $(call unzip-sec-file) - -$(SUPPORT_OUTPUTDIR)/_the.jgss-windows-i586-bin.unzipped: $(JGSS_WIN32_FILES_ZIP) - $(call unzip-native-sec-file) - -$(SUPPORT_OUTPUTDIR)/_the.jgss-windows-x64-bin.unzipped: $(JGSS_WIN64_FILES_ZIP) - $(call unzip-native-sec-file) - -ifneq ($(wildcard $(SEC_FILES_ZIP)), ) - IMPORT_TARGET_FILES += $(SUPPORT_OUTPUTDIR)/_the.sec-bin.unzipped - ifeq ($(OPENJDK_TARGET_OS), windows) - IMPORT_TARGET_FILES += $(SUPPORT_OUTPUTDIR)/_the.sec-windows-bin.unzipped - ifeq ($(OPENJDK_TARGET_CPU), x86) - IMPORT_TARGET_FILES += $(SUPPORT_OUTPUTDIR)/_the.jgss-windows-i586-bin.unzipped - endif - ifeq ($(OPENJDK_TARGET_CPU), x86_64) - IMPORT_TARGET_FILES += $(SUPPORT_OUTPUTDIR)/_the.jgss-windows-x64-bin.unzipped - endif - endif -endif - -################################################################################ - -sec: $(IMPORT_TARGET_FILES) - -all: sec - -.PHONY: sec all diff -r d66751750b72 -r c10dbcaed048 make/autoconf/build-aux/config.guess --- a/make/autoconf/build-aux/config.guess Wed May 30 11:36:46 2018 -0700 +++ b/make/autoconf/build-aux/config.guess Thu May 31 13:39:26 2018 -0700 @@ -86,6 +86,17 @@ fi fi +# Test and fix little endian MIPS. +if [ "x$OUT" = x ]; then + if [ `uname -s` = Linux ]; then + if [ `uname -m` = mipsel ]; then + OUT=mipsel-unknown-linux-gnu + elif [ `uname -m` = mips64el ]; then + OUT=mips64el-unknown-linux-gnu + fi + fi +fi + # Test and fix cpu on Macosx when C preprocessor is not on the path echo $OUT | grep i386-apple-darwin > /dev/null 2> /dev/null if test $? = 0; then diff -r d66751750b72 -r c10dbcaed048 make/gensrc/Gensrc-jdk.scripting.nashorn.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/gensrc/Gensrc-jdk.scripting.nashorn.gmk Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,51 @@ +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include TextFileProcessing.gmk + +################################################################################ + +# Version file needs to be processed with version numbers +VERSION_FILE := jdk/nashorn/internal/runtime/resources/version.properties + +$(eval $(call SetupTextFileProcessing, BUILD_VERSION_FILE, \ + SOURCE_FILES := $(TOPDIR)/src/$(MODULE)/share/classes/$(VERSION_FILE).template, \ + OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/$(VERSION_FILE), \ + REPLACEMENTS := \ + @@VERSION_STRING@@ => $(VERSION_STRING) ; \ + @@VERSION_SHORT@@ => $(VERSION_SHORT) , \ +)) + +TARGETS += $(NASGEN_RUN_FILE) $(BUILD_VERSION_FILE) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all default diff -r d66751750b72 -r c10dbcaed048 make/lib/Lib-jdk.net.gmk --- a/make/lib/Lib-jdk.net.gmk Wed May 30 11:36:46 2018 -0700 +++ b/make/lib/Lib-jdk.net.gmk Thu May 31 13:39:26 2018 -0700 @@ -27,7 +27,7 @@ ################################################################################ -ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux), ) +ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx), ) $(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \ NAME := extnet, \ diff -r d66751750b72 -r c10dbcaed048 make/test/JtregNativeHotspot.gmk --- a/make/test/JtregNativeHotspot.gmk Wed May 30 11:36:46 2018 -0700 +++ b/make/test/JtregNativeHotspot.gmk Thu May 31 13:39:26 2018 -0700 @@ -134,6 +134,11 @@ -I$(VM_TESTBASE_DIR)/nsk/share/jvmti \ -I$(VM_TESTBASE_DIR)/nsk/share/jvmti/aod +NSK_AOD_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/aod \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libThreadController := $(NSK_MONITORING_INCLUDES) @@ -823,6 +828,12 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach050Agent00 := $(NSK_JVMTI_AOD_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach002Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent00 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent01 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent02 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent03 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine09agent00 := $(NSK_AOD_INCLUDES) + ################################################################################ # Platform specific setup @@ -851,8 +862,6 @@ BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c - # Disable warning until JDK-8203802 is fixed - BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtimers += -wd4477 else BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbootclssearch_agent += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsystemclssearch_agent += -lpthread diff -r d66751750b72 -r c10dbcaed048 src/hotspot/cpu/sparc/assembler_sparc.hpp --- a/src/hotspot/cpu/sparc/assembler_sparc.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/cpu/sparc/assembler_sparc.hpp Thu May 31 13:39:26 2018 -0700 @@ -783,8 +783,10 @@ void flush() { #ifdef VALIDATE_PIPELINE assert(_delay_state == NoDelay, "Ending code with a delay-slot."); +#ifdef COMPILER2 validate_no_pipeline_hazards(); #endif +#endif AbstractAssembler::flush(); } diff -r d66751750b72 -r c10dbcaed048 src/hotspot/os/windows/os_perf_windows.cpp --- a/src/hotspot/os/windows/os_perf_windows.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/os/windows/os_perf_windows.cpp Thu May 31 13:39:26 2018 -0700 @@ -118,6 +118,11 @@ bool initialized; } MultiCounterQuerySetS, *MultiCounterQuerySetP; +typedef struct { + MultiCounterQuerySetS set; + int process_index; +} ProcessQueryS, *ProcessQueryP; + static void pdh_cleanup(HQUERY* const query, HCOUNTER* const counter) { if (counter != NULL && *counter != NULL) { PdhDll::PdhRemoveCounter(*counter); @@ -158,7 +163,7 @@ } } -static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) { +static void destroy_multi_counter_query(MultiCounterQuerySetP counter_query_set) { for (int i = 0; i < counter_query_set->size; i++) { for (int j = 0; j < counter_query_set->queries[i].noOfCounters; ++j) { pdh_cleanup(NULL, &counter_query_set->queries[i].counters[j]); @@ -167,9 +172,18 @@ pdh_cleanup(&counter_query_set->queries[i].query.query, NULL); } FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query_set->queries); +} + +static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) { + destroy_multi_counter_query(counter_query_set); FREE_C_HEAP_ARRAY(MultiCounterQuerySetS, counter_query_set); } +static void destroy_counter_query(ProcessQueryP process_query) { + destroy_multi_counter_query(&process_query->set); + FREE_C_HEAP_ARRAY(ProcessQueryS, process_query); +} + static int open_query(HQUERY* query) { return PdhDll::PdhOpenQuery(NULL, 0, query); } @@ -204,6 +218,11 @@ return OS_OK; } +static int allocate_counters(ProcessQueryP process_query, size_t nofCounters) { + assert(process_query != NULL, "invariant"); + return allocate_counters(&process_query->set, nofCounters); +} + static void deallocate_counters(MultiCounterQueryP query) { if (query->counters != NULL) { FREE_C_HEAP_ARRAY(char, query->counters); @@ -262,7 +281,6 @@ static OSReturn add_process_counter(MultiCounterQueryP query, int slot_index, const char* path, bool first_sample_on_init) { assert(query != NULL, "invariant"); - assert(query != NULL, "invariant"); assert(slot_index < query->noOfCounters, "invariant"); assert(query->counters[slot_index] == NULL, "invariant"); const OSReturn ret = add_counter(query, &query->counters[slot_index], path, first_sample_on_init); @@ -326,13 +344,15 @@ * (in order to keep this index valid when the list resets from underneath, * ensure to call current_query_index_for_process() before every query involving * Process object instance data). +* +* if unable to query, returns OS_ERR(-1) */ static int current_query_index_for_process() { assert(process_image_name != NULL, "invariant"); assert(pdh_IDProcess_counter_fmt != NULL, "invariant"); HQUERY tmpQuery = NULL; if (open_query(&tmpQuery) != ERROR_SUCCESS) { - return 0; + return OS_ERR; } char counter[512]; HCOUNTER handle_counter = NULL; @@ -342,12 +362,12 @@ assert(strlen(counter) < sizeof(counter), "invariant"); if (PdhDll::PdhAddCounter(tmpQuery, counter, 0, &handle_counter) != ERROR_SUCCESS) { pdh_cleanup(&tmpQuery, &handle_counter); - return 0; + return OS_ERR; } const PDH_STATUS res = PdhDll::PdhCollectQueryData(tmpQuery); if (res == PDH_INVALID_HANDLE || res == PDH_NO_DATA) { pdh_cleanup(&tmpQuery, &handle_counter); - return 0; + return OS_ERR; } else { PDH_FMT_COUNTERVALUE counter_value; formatted_counter_value(handle_counter, PDH_FMT_LONG, &counter_value); @@ -359,24 +379,28 @@ } } pdh_cleanup(&tmpQuery, NULL); - return 0; + return OS_ERR; } -static MultiCounterQuerySetP create_process_counter_query() { - MultiCounterQuerySetP const query = NEW_C_HEAP_ARRAY(MultiCounterQuerySetS, 1, mtInternal); - memset(query, 0, sizeof(MultiCounterQuerySetS)); +static ProcessQueryP create_process_query() { const int current_process_idx = current_query_index_for_process(); - query->queries = NEW_C_HEAP_ARRAY(MultiCounterQueryS, current_process_idx + 1, mtInternal); - memset(query->queries, 0, sizeof(MultiCounterQueryS) * (current_process_idx + 1)); - query->size = current_process_idx + 1; - return query; + if (OS_ERR == current_process_idx) { + return NULL; + } + ProcessQueryP const process_query = NEW_C_HEAP_ARRAY(ProcessQueryS, 1, mtInternal); + memset(process_query, 0, sizeof(ProcessQueryS)); + process_query->set.queries = NEW_C_HEAP_ARRAY(MultiCounterQueryS, current_process_idx + 1, mtInternal); + memset(process_query->set.queries, 0, sizeof(MultiCounterQueryS) * (current_process_idx + 1)); + process_query->process_index = current_process_idx; + process_query->set.size = current_process_idx + 1; + assert(process_query->set.size > process_query->process_index, "invariant"); + return process_query; } -static MultiCounterQueryP current_process_counter_query(MultiCounterQuerySetP process_query_set) { - assert(process_query_set != NULL, "invariant"); - const int current_query_index = current_query_index_for_process(); - assert(current_query_index < process_query_set->size, "invariant"); - return &process_query_set->queries[current_query_index]; +static MultiCounterQueryP current_process_counter_query(ProcessQueryP process_query) { + assert(process_query != NULL, "invariant"); + assert(process_query->process_index < process_query->set.size, "invariant"); + return &process_query->set.queries[process_query->process_index]; } static void clear_multi_counter(MultiCounterQueryP query) { @@ -384,19 +408,46 @@ pdh_cleanup(NULL, &query->counters[i]); } pdh_cleanup(&query->query.query, NULL); + query->initialized = false; } -static int collect_process_query_data(MultiCounterQuerySetP counter_query_set) { +static int ensure_valid_process_query_index(ProcessQueryP process_query) { + assert(process_query != NULL, "invariant"); + const int previous_process_idx = process_query->process_index; + if (previous_process_idx == 0) { + return previous_process_idx; + } const int current_process_idx = current_query_index_for_process(); - while (current_process_idx < counter_query_set->size - 1) { - const int new_size = --counter_query_set->size; - clear_multi_counter(&counter_query_set->queries[new_size]); + if (current_process_idx == previous_process_idx || OS_ERR == current_process_idx || + current_process_idx >= process_query->set.size) { + return previous_process_idx; } - return collect_query_data(&counter_query_set->queries[current_process_idx]); + + assert(current_process_idx >= 0 && current_process_idx < process_query->set.size, "out of bounds!"); + while (current_process_idx < process_query->set.size - 1) { + const int new_size = --process_query->set.size; + clear_multi_counter(&process_query->set.queries[new_size]); + } + assert(current_process_idx < process_query->set.size, "invariant"); + process_query->process_index = current_process_idx; + return current_process_idx; } -static int query_process_counter(MultiCounterQuerySetP process_query_set, int slot_index, DWORD format, PDH_FMT_COUNTERVALUE* const value) { - MultiCounterQueryP const current_query = current_process_counter_query(process_query_set); +static MultiCounterQueryP current_process_query(ProcessQueryP process_query) { + assert(process_query != NULL, "invariant"); + const int current_process_idx = ensure_valid_process_query_index(process_query); + assert(current_process_idx == process_query->process_index, "invariant"); + assert(current_process_idx < process_query->set.size, "invariant"); + return &process_query->set.queries[current_process_idx]; +} + +static int collect_process_query_data(ProcessQueryP process_query) { + assert(process_query != NULL, "invariant"); + return collect_query_data(current_process_query(process_query)); +} + +static int query_process_counter(ProcessQueryP process_query, int slot_index, DWORD format, PDH_FMT_COUNTERVALUE* const value) { + MultiCounterQueryP const current_query = current_process_counter_query(process_query); assert(current_query != NULL, "invariant"); assert(slot_index < current_query->noOfCounters, "invariant"); assert(current_query->counters[slot_index] != NULL, "invariant"); @@ -810,7 +861,7 @@ return initialize_cpu_query_counters(cpu_query, pdh_counter_idx); } -static int initialize_process_counter(MultiCounterQuerySetP query_set, int slot_index, DWORD pdh_counter_index) { +static int initialize_process_counter(ProcessQueryP process_query, int slot_index, DWORD pdh_counter_index) { char* localized_process_object; if (lookup_name_by_index(PDH_PROCESS_IDX, &localized_process_object) != OS_OK) { return OS_ERR; @@ -821,7 +872,7 @@ return OS_ERR; } assert(localized_counter_name != NULL, "invariant"); - for (int i = 0; i < query_set->size; ++i) { + for (int i = 0; i < process_query->set.size; ++i) { char instanceIndexBuffer[32]; const char* counter_path = make_fully_qualified_counter_path(localized_process_object, localized_counter_name, @@ -830,7 +881,7 @@ if (counter_path == NULL) { return OS_ERR; } - MultiCounterQueryP const query = &query_set->queries[i]; + MultiCounterQueryP const query = &process_query->set.queries[i]; if (add_process_counter(query, slot_index, counter_path, true)) { return OS_ERR; } @@ -839,8 +890,9 @@ } static CounterQueryP create_counter_query(DWORD pdh_object_idx, DWORD pdh_counter_idx) { - assert(is_valid_pdh_index(pdh_object_idx), "invariant"); - assert(is_valid_pdh_index(pdh_counter_idx), "invariant"); + if (!((is_valid_pdh_index(pdh_object_idx) && is_valid_pdh_index(pdh_counter_idx)))) { + return NULL; + } CounterQueryP const query = create_counter_query(); const char* object = pdh_localized_artifact(pdh_object_idx); assert(object != NULL, "invariant"); @@ -917,7 +969,7 @@ friend class CPUPerformanceInterface; private: CounterQueryP _context_switches; - MultiCounterQuerySetP _process_cpu_load; + ProcessQueryP _process_cpu_load; MultiCounterQueryP _machine_cpu_load; int cpu_load(int which_logical_cpu, double* cpu_load); @@ -963,34 +1015,28 @@ bool CPUPerformanceInterface::CPUPerformance::initialize() { if (!pdh_acquire()) { - return false; + return true; } _context_switches = create_counter_query(PDH_SYSTEM_IDX, PDH_CONTEXT_SWITCH_RATE_IDX); - if (_context_switches == NULL) { - return false; - } - _process_cpu_load = create_process_counter_query(); + _process_cpu_load = create_process_query(); if (_process_cpu_load == NULL) { - return false; + return true; } if (allocate_counters(_process_cpu_load, 2) != OS_OK) { - return false; + return true; } if (initialize_process_counter(_process_cpu_load, 0, PDH_PROCESSOR_TIME_IDX) != OS_OK) { - return false; + return true; } if (initialize_process_counter(_process_cpu_load, 1, PDH_PRIV_PROCESSOR_TIME_IDX) != OS_OK) { - return false; + return true; } - _process_cpu_load->initialized = true; - + _process_cpu_load->set.initialized = true; _machine_cpu_load = create_multi_counter_query(); if (_machine_cpu_load == NULL) { - return false; + return true; } - if (initialize_cpu_query(_machine_cpu_load, PDH_PROCESSOR_TIME_IDX) != OS_OK) { - return false; - } + initialize_cpu_query(_machine_cpu_load, PDH_PROCESSOR_TIME_IDX); return true; } @@ -1044,12 +1090,13 @@ } int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) { + *cpu_load = .0; + if (_machine_cpu_load == NULL || !_machine_cpu_load->initialized) { + return OS_ERR; + } assert(_machine_cpu_load != NULL, "invariant"); assert(which_logical_cpu < _machine_cpu_load->noOfCounters, "invariant"); - *cpu_load = .0; - if (!_machine_cpu_load->initialized) { - return OS_ERR; - } + if (collect_query_data(_machine_cpu_load)) { return OS_ERR; } @@ -1062,11 +1109,11 @@ } int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) { - assert(_process_cpu_load != NULL, "invariant"); *cpu_load = .0; - if (!_process_cpu_load->initialized) { + if (_process_cpu_load == NULL || !_process_cpu_load->set.initialized) { return OS_ERR; } + assert(_process_cpu_load != NULL, "invariant"); if (collect_process_query_data(_process_cpu_load)) { return OS_ERR; } @@ -1090,9 +1137,11 @@ *pjvmUserLoad = .0; *pjvmKernelLoad = .0; *psystemTotalLoad = .0; - if (!_process_cpu_load->initialized) { + + if (_process_cpu_load == NULL || !_process_cpu_load->set.initialized) { return OS_ERR; } + assert(_process_cpu_load != NULL, "invariant"); if (collect_process_query_data(_process_cpu_load)) { return OS_ERR; } @@ -1138,9 +1187,10 @@ int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) { assert(rate != NULL, "invariant"); *rate = .0; - if (!_context_switches->initialized) { + if (_context_switches == NULL || !_context_switches->initialized) { return OS_ERR; } + assert(_context_switches != NULL, "invariant"); if (collect_query_data(_context_switches) != OS_OK) { return OS_ERR; } diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/classfile/classLoaderData.hpp --- a/src/hotspot/share/classfile/classLoaderData.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/classfile/classLoaderData.hpp Thu May 31 13:39:26 2018 -0700 @@ -400,9 +400,16 @@ static ClassLoaderData* class_loader_data_or_null(oop loader); static ClassLoaderData* anonymous_class_loader_data(Handle loader); - + // Returns Klass* of associated class loader, or NULL if associated loader is . + // Also works if unloading. Klass* class_loader_klass() const { return _class_loader_klass; } + + // Returns Name of associated class loader. + // Returns NULL if associated class loader is or if no name has been set for + // this loader. + // Also works if unloading. Symbol* class_loader_name() const { return _class_loader_name; } + JFR_ONLY(DEFINE_TRACE_ID_METHODS;) }; diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/classfile/classLoaderExt.cpp --- a/src/hotspot/share/classfile/classLoaderExt.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/classfile/classLoaderExt.cpp Thu May 31 13:39:26 2018 -0700 @@ -55,8 +55,10 @@ void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) { #if INCLUDE_CDS - warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended"); - FileMapInfo::current_info()->header()->set_has_platform_or_app_classes(false); + if (UseSharedSpaces) { + warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended"); + FileMapInfo::current_info()->header()->set_has_platform_or_app_classes(false); + } #endif ClassLoader::add_to_boot_append_entries(new_entry); } diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/gc/shared/oopStorage.cpp --- a/src/hotspot/share/gc/shared/oopStorage.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/gc/shared/oopStorage.cpp Thu May 31 13:39:26 2018 -0700 @@ -907,7 +907,8 @@ // Parallel iteration support uint OopStorage::BasicParState::default_estimated_thread_count(bool concurrent) { - return concurrent ? ConcGCThreads : ParallelGCThreads; + uint configured = concurrent ? ConcGCThreads : ParallelGCThreads; + return MAX2(1u, configured); // Never estimate zero threads. } OopStorage::BasicParState::BasicParState(const OopStorage* storage, diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/gc/shared/oopStorage.hpp diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/interpreter/bytecodeInterpreterProfiling.hpp --- a/src/hotspot/share/interpreter/bytecodeInterpreterProfiling.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/interpreter/bytecodeInterpreterProfiling.hpp Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,25 +30,10 @@ #ifndef SHARE_VM_INTERPRETER_BYTECODEINTERPRETERPROFILING_HPP #define SHARE_VM_INTERPRETER_BYTECODEINTERPRETERPROFILING_HPP - -// Global settings ///////////////////////////////////////////////////////////// - - -// Enables profiling support. -#if defined(COMPILER2) -#define CC_INTERP_PROFILE -#endif - -// Enables assertions for profiling code (also works in product-builds). -// #define CC_INTERP_PROFILE_WITH_ASSERTIONS - - #ifdef CC_INTERP // Empty dummy implementations if profiling code is switched off. ////////////// -#ifndef CC_INTERP_PROFILE - #define SET_MDX(mdx) #define BI_PROFILE_GET_OR_CREATE_METHOD_DATA(exception_handler) \ @@ -69,240 +54,6 @@ #define BI_PROFILE_UPDATE_VIRTUALCALL(receiver) #define BI_PROFILE_UPDATE_SWITCH(switch_index) - -#else - - -// Non-dummy implementations /////////////////////////////////////////////////// - -// Accessors for the current method data pointer 'mdx'. -#define MDX() (istate->mdx()) -#define SET_MDX(mdx) \ - if (TraceProfileInterpreter) { \ - /* Let it look like TraceBytecodes' format. */ \ - tty->print_cr("[%d] %4d " \ - "mdx " PTR_FORMAT "(%d)" \ - " " \ - " \t-> " PTR_FORMAT "(%d)", \ - (int) THREAD->osthread()->thread_id(), \ - BCI(), \ - p2i(MDX()), \ - (MDX() == NULL \ - ? 0 \ - : istate->method()->method_data()->dp_to_di((address)MDX())), \ - p2i(mdx), \ - istate->method()->method_data()->dp_to_di((address)mdx) \ - ); \ - }; \ - istate->set_mdx(mdx); - - -// Dumps the profiling method data for the current method. -#ifdef PRODUCT -#define BI_PROFILE_PRINT_METHOD_DATA() -#else // PRODUCT -#define BI_PROFILE_PRINT_METHOD_DATA() \ - { \ - ttyLocker ttyl; \ - MethodData *md = istate->method()->method_data(); \ - tty->cr(); \ - tty->print("method data at mdx " PTR_FORMAT "(0) for", \ - p2i(md->data_layout_at(md->bci_to_di(0)))); \ - istate->method()->print_short_name(tty); \ - tty->cr(); \ - if (md != NULL) { \ - md->print_data_on(tty); \ - address mdx = (address) MDX(); \ - if (mdx != NULL) { \ - tty->print_cr("current mdx " PTR_FORMAT "(%d)", \ - p2i(mdx), \ - istate->method()->method_data()->dp_to_di(mdx)); \ - } \ - } else { \ - tty->print_cr("no method data"); \ - } \ - } -#endif // PRODUCT - - -// Gets or creates the profiling method data and initializes mdx. -#define BI_PROFILE_GET_OR_CREATE_METHOD_DATA(exception_handler) \ - if (ProfileInterpreter && MDX() == NULL) { \ - /* Mdx is not yet initialized for this activation. */ \ - MethodData *md = istate->method()->method_data(); \ - if (md == NULL) { \ - MethodCounters* mcs; \ - GET_METHOD_COUNTERS(mcs); \ - /* The profiling method data doesn't exist for this method, */ \ - /* create it if the counters have overflowed. */ \ - if (mcs->invocation_counter() \ - ->reached_ProfileLimit(mcs->backedge_counter())) { \ - /* Must use CALL_VM, because an async exception may be pending. */ \ - CALL_VM((InterpreterRuntime::profile_method(THREAD)), \ - exception_handler); \ - md = istate->method()->method_data(); \ - if (md != NULL) { \ - if (TraceProfileInterpreter) { \ - BI_PROFILE_PRINT_METHOD_DATA(); \ - } \ - Method *m = istate->method(); \ - int bci = m->bci_from(pc); \ - jint di = md->bci_to_di(bci); \ - SET_MDX(md->data_layout_at(di)); \ - } \ - } \ - } else { \ - /* The profiling method data exists, align the method data pointer */ \ - /* mdx to the current bytecode index. */ \ - if (TraceProfileInterpreter) { \ - BI_PROFILE_PRINT_METHOD_DATA(); \ - } \ - SET_MDX(md->data_layout_at(md->bci_to_di(BCI()))); \ - } \ - } - - -// Asserts that the current method data pointer mdx corresponds -// to the current bytecode. -#if defined(CC_INTERP_PROFILE_WITH_ASSERTIONS) -#define BI_PROFILE_CHECK_MDX() \ - { \ - MethodData *md = istate->method()->method_data(); \ - address mdx = (address) MDX(); \ - address mdx2 = (address) md->data_layout_at(md->bci_to_di(BCI())); \ - guarantee(md != NULL, "1"); \ - guarantee(mdx != NULL, "2"); \ - guarantee(mdx2 != NULL, "3"); \ - if (mdx != mdx2) { \ - BI_PROFILE_PRINT_METHOD_DATA(); \ - fatal3("invalid mdx at bci %d:" \ - " was " PTR_FORMAT \ - " but expected " PTR_FORMAT, \ - BCI(), \ - mdx, \ - mdx2); \ - } \ - } -#else -#define BI_PROFILE_CHECK_MDX() -#endif - - -// Aligns the method data pointer mdx to the current bytecode index. -#define BI_PROFILE_ALIGN_TO_CURRENT_BCI() \ - if (ProfileInterpreter && MDX() != NULL) { \ - MethodData *md = istate->method()->method_data(); \ - SET_MDX(md->data_layout_at(md->bci_to_di(BCI()))); \ - } - - -// Updates profiling data for a jump. -#define BI_PROFILE_UPDATE_JUMP() \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - JumpData::increment_taken_count_no_overflow(MDX()); \ - /* Remember last branch taken count. */ \ - mdo_last_branch_taken_count = JumpData::taken_count(MDX()); \ - SET_MDX(JumpData::advance_taken(MDX())); \ - } - - -// Updates profiling data for a taken/not taken branch. -#define BI_PROFILE_UPDATE_BRANCH(is_taken) \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - if (is_taken) { \ - BranchData::increment_taken_count_no_overflow(MDX()); \ - /* Remember last branch taken count. */ \ - mdo_last_branch_taken_count = BranchData::taken_count(MDX()); \ - SET_MDX(BranchData::advance_taken(MDX())); \ - } else { \ - BranchData::increment_not_taken_count_no_overflow(MDX()); \ - SET_MDX(BranchData::advance_not_taken(MDX())); \ - } \ - } - - -// Updates profiling data for a ret with given bci. -#define BI_PROFILE_UPDATE_RET(bci) \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - MethodData *md = istate->method()->method_data(); \ -/* FIXME: there is more to do here than increment and advance(mdx)! */ \ - CounterData::increment_count_no_overflow(MDX()); \ - SET_MDX(RetData::advance(md, bci)); \ - } - -// Decrement counter at checkcast if the subtype check fails (as template -// interpreter does!). -#define BI_PROFILE_SUBTYPECHECK_FAILED(receiver) \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - ReceiverTypeData::increment_receiver_count_no_overflow(MDX(), receiver); \ - ReceiverTypeData::decrement_count(MDX()); \ - } - -// Updates profiling data for a checkcast (was a null seen? which receiver?). -#define BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver) \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - if (null_seen) { \ - ReceiverTypeData::set_null_seen(MDX()); \ - } else { \ - /* Template interpreter doesn't increment count. */ \ - /* ReceiverTypeData::increment_count_no_overflow(MDX()); */ \ - ReceiverTypeData::increment_receiver_count_no_overflow(MDX(), receiver); \ - } \ - SET_MDX(ReceiverTypeData::advance(MDX())); \ - } - - -// Updates profiling data for an instanceof (was a null seen? which receiver?). -#define BI_PROFILE_UPDATE_INSTANCEOF(null_seen, receiver) \ - BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver) - - -// Updates profiling data for a call. -#define BI_PROFILE_UPDATE_CALL() \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - CounterData::increment_count_no_overflow(MDX()); \ - SET_MDX(CounterData::advance(MDX())); \ - } - - -// Updates profiling data for a final call. -#define BI_PROFILE_UPDATE_FINALCALL() \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - VirtualCallData::increment_count_no_overflow(MDX()); \ - SET_MDX(VirtualCallData::advance(MDX())); \ - } - - -// Updates profiling data for a virtual call with given receiver Klass. -#define BI_PROFILE_UPDATE_VIRTUALCALL(receiver) \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - VirtualCallData::increment_receiver_count_no_overflow(MDX(), receiver); \ - SET_MDX(VirtualCallData::advance(MDX())); \ - } - - -// Updates profiling data for a switch (tabelswitch or lookupswitch) with -// given taken index (-1 means default case was taken). -#define BI_PROFILE_UPDATE_SWITCH(switch_index) \ - if (ProfileInterpreter && MDX() != NULL) { \ - BI_PROFILE_CHECK_MDX(); \ - MultiBranchData::increment_count_no_overflow(MDX(), switch_index); \ - SET_MDX(MultiBranchData::advance(MDX(), switch_index)); \ - } - - -// The end ///////////////////////////////////////////////////////////////////// - -#endif // CC_INTERP_PROFILE - #endif // CC_INTERP #endif // SHARE_VM_INTERPRETER_BYTECODECINTERPRETERPROFILING_HPP diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/interpreter/linkResolver.cpp --- a/src/hotspot/share/interpreter/linkResolver.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/interpreter/linkResolver.cpp Thu May 31 13:39:26 2018 -0700 @@ -688,19 +688,21 @@ CHECK); if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving field" - " \"%s\" the class loader %s of the referring class, " - "%s, and the class loader %s for the field's resolved " - "type, %s, have different Class objects for that type"; - char* field_name = field->as_C_string(); + " \"%s\" of type %s, the class loader %s of the current class, " + "%s, and the class loader %s for the field's defining " + "type, %s, have different Class objects for type %s"; + const char* field_name = field->as_C_string(); const char* loader1_name = java_lang_ClassLoader::describe_external(ref_loader()); - char* sel = sel_klass->name()->as_C_string(); + const char* sel = sel_klass->external_name(); const char* loader2_name = java_lang_ClassLoader::describe_external(sel_loader()); - char* failed_type_name = failed_type_symbol->as_C_string(); - size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) + - strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1; + const char* failed_type_name = failed_type_symbol->as_klass_external_name(); + const char* curr_klass_name = current_klass->external_name(); + size_t buflen = strlen(msg) + strlen(field_name) + 2 * strlen(failed_type_name) + + strlen(loader1_name) + strlen(curr_klass_name) + + strlen(loader2_name) + strlen(sel) + 1; char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, msg, field_name, loader1_name, sel, loader2_name, - failed_type_name); + jio_snprintf(buf, buflen, msg, field_name, failed_type_name, loader1_name, + curr_klass_name, loader2_name, sel, failed_type_name); THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); } } diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace.cpp --- a/src/hotspot/share/memory/metaspace.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/memory/metaspace.cpp Thu May 31 13:39:26 2018 -0700 @@ -601,11 +601,12 @@ void MetaspaceUtils::print_report(outputStream* out, size_t scale, int flags) { const bool print_loaders = (flags & rf_show_loaders) > 0; + const bool print_classes = (flags & rf_show_classes) > 0; const bool print_by_chunktype = (flags & rf_break_down_by_chunktype) > 0; const bool print_by_spacetype = (flags & rf_break_down_by_spacetype) > 0; // Some report options require walking the class loader data graph. - PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_by_chunktype); + PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_classes, print_by_chunktype); if (print_loaders) { out->cr(); out->print_cr("Usage per loader:"); diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace.hpp --- a/src/hotspot/share/memory/metaspace.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/memory/metaspace.hpp Thu May 31 13:39:26 2018 -0700 @@ -389,7 +389,9 @@ // Print details about the underlying virtual spaces. rf_show_vslist = (1 << 3), // Print metaspace map. - rf_show_vsmap = (1 << 4) + rf_show_vsmap = (1 << 4), + // If show_loaders: show loaded classes for each loader. + rf_show_classes = (1 << 5) }; // This will print out a basic metaspace usage report but diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +35,7 @@ : DCmdWithParser(output, heap) , _basic("basic", "Prints a basic summary (does not need a safepoint).", "BOOLEAN", false, "false") , _show_loaders("show-loaders", "Shows usage by class loader.", "BOOLEAN", false, "false") + , _show_classes("show-classes", "If show-loaders is set, shows loaded classes for each loader.", "BOOLEAN", false, "false") , _by_chunktype("by-chunktype", "Break down numbers by chunk type.", "BOOLEAN", false, "false") , _by_spacetype("by-spacetype", "Break down numbers by loader type.", "BOOLEAN", false, "false") , _show_vslist("vslist", "Shows details about the underlying virtual space.", "BOOLEAN", false, "false") @@ -44,6 +46,7 @@ { _dcmdparser.add_dcmd_option(&_basic); _dcmdparser.add_dcmd_option(&_show_loaders); + _dcmdparser.add_dcmd_option(&_show_classes); _dcmdparser.add_dcmd_option(&_by_chunktype); _dcmdparser.add_dcmd_option(&_by_spacetype); _dcmdparser.add_dcmd_option(&_show_vslist); @@ -87,6 +90,7 @@ // Full mode. Requires safepoint. int flags = 0; if (_show_loaders.value()) flags |= MetaspaceUtils::rf_show_loaders; + if (_show_classes.value()) flags |= MetaspaceUtils::rf_show_classes; if (_by_chunktype.value()) flags |= MetaspaceUtils::rf_break_down_by_chunktype; if (_by_spacetype.value()) flags |= MetaspaceUtils::rf_break_down_by_spacetype; if (_show_vslist.value()) flags |= MetaspaceUtils::rf_show_vslist; diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +40,7 @@ DCmdArgument _show_vslist; DCmdArgument _show_vsmap; DCmdArgument _scale; + DCmdArgument _show_classes; public: MetaspaceDCmd(outputStream* output, bool heap); static const char* name() { diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp --- a/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp Thu May 31 13:39:26 2018 -0700 @@ -22,8 +22,10 @@ * */ #include "precompiled.hpp" -#include "classfile/classLoaderData.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/javaClasses.hpp" #include "memory/metaspace/printCLDMetaspaceInfoClosure.hpp" +#include "memory/metaspace/printMetaspaceInfoKlassClosure.hpp" #include "memory/resourceArea.hpp" #include "runtime/safepoint.hpp" #include "utilities/globalDefinitions.hpp" @@ -32,19 +34,31 @@ namespace metaspace { -PrintCLDMetaspaceInfoClosure::PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, bool break_down_by_chunktype) -: _out(out), _scale(scale), _do_print(do_print), _break_down_by_chunktype(break_down_by_chunktype) -, _num_loaders(0) +PrintCLDMetaspaceInfoClosure::PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, + bool do_print_classes, bool break_down_by_chunktype) +: _out(out), _scale(scale), _do_print(do_print), _do_print_classes(do_print_classes) +, _break_down_by_chunktype(break_down_by_chunktype) +, _num_loaders(0), _num_loaders_unloading(0), _num_loaders_without_metaspace(0) { memset(_num_loaders_by_spacetype, 0, sizeof(_num_loaders_by_spacetype)); } +static const char* classes_plural(uintx num) { + return num == 1 ? "" : "es"; +} + void PrintCLDMetaspaceInfoClosure::do_cld(ClassLoaderData* cld) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); + if (cld->is_unloading()) { + _num_loaders_unloading ++; + return; + } + ClassLoaderMetaspace* msp = cld->metaspace_or_null(); if (msp == NULL) { + _num_loaders_without_metaspace ++; return; } @@ -63,17 +77,73 @@ _out->print(UINTX_FORMAT_W(4) ": ", _num_loaders); - if (cld->is_anonymous()) { - _out->print("ClassLoaderData " PTR_FORMAT " for anonymous class", p2i(cld)); + // Print "CLD for [,] instance of " + // or "CLD for , loaded by [,] instance of " + + ResourceMark rm; + const char* name = NULL; + const char* class_name = NULL; + + // Note: this should also work if unloading: + Klass* k = cld->class_loader_klass(); + if (k != NULL) { + class_name = k->external_name(); + Symbol* s = cld->class_loader_name(); + if (s != NULL) { + name = s->as_C_string(); + } } else { - ResourceMark rm; - _out->print("ClassLoaderData " PTR_FORMAT " for %s", p2i(cld), cld->loader_name()); + name = ""; } + // Print + _out->print("CLD " PTR_FORMAT, p2i(cld)); if (cld->is_unloading()) { _out->print(" (unloading)"); } + _out->print(":"); + if (cld->is_anonymous()) { + _out->print(" , loaded by"); + } + if (name != NULL) { + _out->print(" \"%s\"", name); + } + if (class_name != NULL) { + _out->print(" instance of %s", class_name); + } + if (_do_print_classes) { + streamIndentor sti(_out, 6); + _out->cr_indent(); + _out->print("Loaded classes: "); + PrintMetaspaceInfoKlassClosure pkic(_out, true); + cld->classes_do(&pkic); + _out->cr_indent(); + _out->print("-total-: "); + _out->print(UINTX_FORMAT " class%s", pkic._num_classes, classes_plural(pkic._num_classes)); + if (pkic._num_instance_classes > 0 || pkic._num_array_classes > 0) { + _out->print(" ("); + if (pkic._num_instance_classes > 0) { + _out->print(UINTX_FORMAT " instance class%s", pkic._num_instance_classes, + classes_plural(pkic._num_instance_classes)); + } + if (pkic._num_array_classes > 0) { + if (pkic._num_instance_classes > 0) { + _out->print(", "); + } + _out->print(UINTX_FORMAT " array class%s", pkic._num_array_classes, + classes_plural(pkic._num_array_classes)); + } + _out->print(")."); + } + } + + _out->cr(); + + + _out->cr(); + + // Print statistics this_cld_stat.print_on(_out, _scale, _break_down_by_chunktype); _out->cr(); diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp --- a/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp Thu May 31 13:39:26 2018 -0700 @@ -39,17 +39,21 @@ outputStream* const _out; const size_t _scale; const bool _do_print; + const bool _do_print_classes; const bool _break_down_by_chunktype; public: uintx _num_loaders; + uintx _num_loaders_without_metaspace; + uintx _num_loaders_unloading; ClassLoaderMetaspaceStatistics _stats_total; uintx _num_loaders_by_spacetype [Metaspace::MetaspaceTypeCount]; ClassLoaderMetaspaceStatistics _stats_by_spacetype [Metaspace::MetaspaceTypeCount]; - PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, bool break_down_by_chunktype); + PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, + bool do_print_classes, bool break_down_by_chunktype); void do_cld(ClassLoaderData* cld); }; diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "precompiled.hpp" + +#include "classfile/systemDictionary.hpp" +#include "memory/metaspace/printMetaspaceInfoKlassClosure.hpp" +#include "memory/resourceArea.hpp" +#include "oops/constantPool.inline.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klass.hpp" +#include "utilities/constantTag.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + + +namespace metaspace { + +PrintMetaspaceInfoKlassClosure::PrintMetaspaceInfoKlassClosure(outputStream* out, bool do_print) +: _out(out), _do_print(do_print) +, _num_classes(0), _num_instance_classes(0), _num_array_classes(0) { +} + +void PrintMetaspaceInfoKlassClosure::do_klass(Klass* k) { + _num_classes ++; + if (k->is_instance_klass()) { + _num_instance_classes ++; + } else if (k->is_array_klass()) { + _num_array_classes ++; + } + if (_do_print) { + _out->cr_indent(); + _out->print(UINTX_FORMAT_W(4) ": ", _num_classes); + ResourceMark rm; + _out->print("%s", k->external_name()); + } +} + +} // namespace metaspace diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.hpp Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_MEMORY_METASPACE_PRINTMETASPACEINFOKLASSCLOSURE_HPP_ +#define SHARE_MEMORY_METASPACE_PRINTMETASPACEINFOKLASSCLOSURE_HPP_ + +#include "memory/iterator.hpp" +#include "utilities/globalDefinitions.hpp" + +class outputStream; +class InstanceKlass; + +namespace metaspace { + +// Helper class for MetaspaceUtils::print_report() +class PrintMetaspaceInfoKlassClosure : public KlassClosure { +private: + outputStream* const _out; + const bool _do_print; + +public: + uintx _num_classes; + uintx _num_instance_classes; + uintx _num_array_classes; + + PrintMetaspaceInfoKlassClosure(outputStream* out, bool do_print); + void do_klass(Klass* k); + +}; // end: PrintKlassInfoClosure + +} // namespace metaspace + +#endif /* SHARE_MEMORY_METASPACE_PRINTMETASPACEINFOKLASSCLOSURE_HPP_ */ diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/oops/arrayKlass.cpp --- a/src/hotspot/share/oops/arrayKlass.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/oops/arrayKlass.cpp Thu May 31 13:39:26 2018 -0700 @@ -130,7 +130,7 @@ objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) { if (length < 0) { - THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); } if (length > arrayOopDesc::max_array_length(T_ARRAY)) { report_java_out_of_memory("Requested array size exceeds VM limit"); diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/oops/instanceKlass.cpp --- a/src/hotspot/share/oops/instanceKlass.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/oops/instanceKlass.cpp Thu May 31 13:39:26 2018 -0700 @@ -975,7 +975,9 @@ } objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) { - if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + if (length < 0) { + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); + } if (length > arrayOopDesc::max_array_length(T_OBJECT)) { report_java_out_of_memory("Requested array size exceeds VM limit"); JvmtiExport::post_array_size_exhausted(); diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/oops/methodData.cpp --- a/src/hotspot/share/oops/methodData.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/oops/methodData.cpp Thu May 31 13:39:26 2018 -0700 @@ -541,12 +541,6 @@ return mdp; } -#ifdef CC_INTERP -DataLayout* RetData::advance(MethodData *md, int bci) { - return (DataLayout*) md->bci_to_dp(bci); -} -#endif // CC_INTERP - void RetData::print_data_on(outputStream* st, const char* extra) const { print_shared(st, "RetData", extra); uint row; diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/oops/methodData.hpp --- a/src/hotspot/share/oops/methodData.hpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/oops/methodData.hpp Thu May 31 13:39:26 2018 -0700 @@ -232,11 +232,6 @@ static ByteSize cell_offset(int index) { return byte_offset_of(DataLayout, _cells) + in_ByteSize(index * cell_size); } -#ifdef CC_INTERP - static int cell_offset_in_bytes(int index) { - return (int)offset_of(DataLayout, _cells[index]); - } -#endif // CC_INTERP // Return a value which, when or-ed as a byte into _flags, sets the flag. static int flag_number_to_byte_constant(int flag_number) { assert(0 <= flag_number && flag_number < flag_limit, "oob"); @@ -372,41 +367,6 @@ _data = data; } -#ifdef CC_INTERP - // Static low level accessors for DataLayout with ProfileData's semantics. - - static int cell_offset_in_bytes(int index) { - return DataLayout::cell_offset_in_bytes(index); - } - - static void increment_uint_at_no_overflow(DataLayout* layout, int index, - int inc = DataLayout::counter_increment) { - uint count = ((uint)layout->cell_at(index)) + inc; - if (count == 0) return; - layout->set_cell_at(index, (intptr_t) count); - } - - static int int_at(DataLayout* layout, int index) { - return (int)layout->cell_at(index); - } - - static int uint_at(DataLayout* layout, int index) { - return (uint)layout->cell_at(index); - } - - static oop oop_at(DataLayout* layout, int index) { - return cast_to_oop(layout->cell_at(index)); - } - - static void set_intptr_at(DataLayout* layout, int index, intptr_t value) { - layout->set_cell_at(index, (intptr_t) value); - } - - static void set_flag_at(DataLayout* layout, int flag_number) { - layout->set_flag_at(flag_number); - } -#endif // CC_INTERP - public: // Constructor for invalid ProfileData. ProfileData(); @@ -581,20 +541,6 @@ return cell_offset(bit_cell_count); } -#ifdef CC_INTERP - static int bit_data_size_in_bytes() { - return cell_offset_in_bytes(bit_cell_count); - } - - static void set_null_seen(DataLayout* layout) { - set_flag_at(layout, null_seen_flag); - } - - static DataLayout* advance(DataLayout* layout) { - return (DataLayout*) (((address)layout) + (ssize_t)BitData::bit_data_size_in_bytes()); - } -#endif // CC_INTERP - void print_data_on(outputStream* st, const char* extra = NULL) const; }; @@ -639,25 +585,6 @@ set_uint_at(count_off, count); } -#ifdef CC_INTERP - static int counter_data_size_in_bytes() { - return cell_offset_in_bytes(counter_cell_count); - } - - static void increment_count_no_overflow(DataLayout* layout) { - increment_uint_at_no_overflow(layout, count_off); - } - - // Support counter decrementation at checkcast / subtype check failed. - static void decrement_count(DataLayout* layout) { - increment_uint_at_no_overflow(layout, count_off, -1); - } - - static DataLayout* advance(DataLayout* layout) { - return (DataLayout*) (((address)layout) + (ssize_t)CounterData::counter_data_size_in_bytes()); - } -#endif // CC_INTERP - void print_data_on(outputStream* st, const char* extra = NULL) const; }; @@ -728,20 +655,6 @@ return cell_offset(displacement_off_set); } -#ifdef CC_INTERP - static void increment_taken_count_no_overflow(DataLayout* layout) { - increment_uint_at_no_overflow(layout, taken_off_set); - } - - static DataLayout* advance_taken(DataLayout* layout) { - return (DataLayout*) (((address)layout) + (ssize_t)int_at(layout, displacement_off_set)); - } - - static uint taken_count(DataLayout* layout) { - return (uint) uint_at(layout, taken_off_set); - } -#endif // CC_INTERP - // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -1302,43 +1215,6 @@ // GC support virtual void clean_weak_klass_links(bool always_clean); -#ifdef CC_INTERP - static int receiver_type_data_size_in_bytes() { - return cell_offset_in_bytes(static_cell_count()); - } - - static Klass *receiver_unchecked(DataLayout* layout, uint row) { - Klass* recv = (Klass*)layout->cell_at(receiver_cell_index(row)); - return recv; - } - - static void increment_receiver_count_no_overflow(DataLayout* layout, Klass *rcvr) { - const int num_rows = row_limit(); - // Receiver already exists? - for (int row = 0; row < num_rows; row++) { - if (receiver_unchecked(layout, row) == rcvr) { - increment_uint_at_no_overflow(layout, receiver_count_cell_index(row)); - return; - } - } - // New receiver, find a free slot. - for (int row = 0; row < num_rows; row++) { - if (receiver_unchecked(layout, row) == NULL) { - set_intptr_at(layout, receiver_cell_index(row), (intptr_t)rcvr); - increment_uint_at_no_overflow(layout, receiver_count_cell_index(row)); - return; - } - } - // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polymorphic case. - increment_count_no_overflow(layout); - } - - static DataLayout* advance(DataLayout* layout) { - return (DataLayout*) (((address)layout) + (ssize_t)ReceiverTypeData::receiver_type_data_size_in_bytes()); - } -#endif // CC_INTERP - void print_receiver_data_on(outputStream* st) const; void print_data_on(outputStream* st, const char* extra = NULL) const; }; @@ -1371,16 +1247,6 @@ return cell_offset(static_cell_count()); } -#ifdef CC_INTERP - static int virtual_call_data_size_in_bytes() { - return cell_offset_in_bytes(static_cell_count()); - } - - static DataLayout* advance(DataLayout* layout) { - return (DataLayout*) (((address)layout) + (ssize_t)VirtualCallData::virtual_call_data_size_in_bytes()); - } -#endif // CC_INTERP - #if INCLUDE_JVMCI static ByteSize method_offset(uint row) { return cell_offset(method_cell_index(row)); @@ -1658,10 +1524,6 @@ return cell_offset(bci_displacement_cell_index(row)); } -#ifdef CC_INTERP - static DataLayout* advance(MethodData *md, int bci); -#endif // CC_INTERP - // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -1726,20 +1588,6 @@ return cell_offset(branch_cell_count); } -#ifdef CC_INTERP - static int branch_data_size_in_bytes() { - return cell_offset_in_bytes(branch_cell_count); - } - - static void increment_not_taken_count_no_overflow(DataLayout* layout) { - increment_uint_at_no_overflow(layout, not_taken_off_set); - } - - static DataLayout* advance_not_taken(DataLayout* layout) { - return (DataLayout*) (((address)layout) + (ssize_t)BranchData::branch_data_size_in_bytes()); - } -#endif // CC_INTERP - // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -1779,20 +1627,6 @@ set_int_at(aindex, value); } -#ifdef CC_INTERP - // Static low level accessors for DataLayout with ArrayData's semantics. - - static void increment_array_uint_at_no_overflow(DataLayout* layout, int index) { - int aindex = index + array_start_off_set; - increment_uint_at_no_overflow(layout, aindex); - } - - static int array_int_at(DataLayout* layout, int index) { - int aindex = index + array_start_off_set; - return int_at(layout, aindex); - } -#endif // CC_INTERP - // Code generation support for subclasses. static ByteSize array_element_offset(int index) { return cell_offset(array_start_off_set + index); @@ -1913,28 +1747,6 @@ return in_ByteSize(relative_displacement_off_set) * cell_size; } -#ifdef CC_INTERP - static void increment_count_no_overflow(DataLayout* layout, int index) { - if (index == -1) { - increment_array_uint_at_no_overflow(layout, default_count_off_set); - } else { - increment_array_uint_at_no_overflow(layout, case_array_start + - index * per_case_cell_count + - relative_count_off_set); - } - } - - static DataLayout* advance(DataLayout* layout, int index) { - if (index == -1) { - return (DataLayout*) (((address)layout) + (ssize_t)array_int_at(layout, default_disaplacement_off_set)); - } else { - return (DataLayout*) (((address)layout) + (ssize_t)array_int_at(layout, case_array_start + - index * per_case_cell_count + - relative_displacement_off_set)); - } - } -#endif // CC_INTERP - // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -2127,13 +1939,11 @@ // adjusted in the event of a change in control flow. // -CC_INTERP_ONLY(class BytecodeInterpreter;) class CleanExtraDataClosure; class MethodData : public Metadata { friend class VMStructs; friend class JVMCIVMStructs; - CC_INTERP_ONLY(friend class BytecodeInterpreter;) private: friend class ProfileData; friend class TypeEntriesAtCall; diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/oops/objArrayKlass.cpp --- a/src/hotspot/share/oops/objArrayKlass.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/oops/objArrayKlass.cpp Thu May 31 13:39:26 2018 -0700 @@ -181,7 +181,7 @@ THROW_OOP_0(Universe::out_of_memory_error_array_size()); } } else { - THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); } } @@ -209,7 +209,7 @@ for (int i = 0; i < rank - 1; ++i) { sizes += 1; if (*sizes < 0) { - THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes)); } } } diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/oops/typeArrayKlass.cpp --- a/src/hotspot/share/oops/typeArrayKlass.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/oops/typeArrayKlass.cpp Thu May 31 13:39:26 2018 -0700 @@ -116,7 +116,7 @@ THROW_OOP_0(Universe::out_of_memory_error_array_size()); } } else { - THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); } } diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/prims/whitebox.cpp --- a/src/hotspot/share/prims/whitebox.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/prims/whitebox.cpp Thu May 31 13:39:26 2018 -0700 @@ -98,6 +98,7 @@ #define CHECK_JNI_EXCEPTION_(env, value) \ do { \ JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \ + THREAD->clear_pending_jni_exception_check(); \ if (HAS_PENDING_EXCEPTION) { \ return(value); \ } \ @@ -106,6 +107,7 @@ #define CHECK_JNI_EXCEPTION(env) \ do { \ JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \ + THREAD->clear_pending_jni_exception_check(); \ if (HAS_PENDING_EXCEPTION) { \ return; \ } \ diff -r d66751750b72 -r c10dbcaed048 src/hotspot/share/runtime/reflection.cpp --- a/src/hotspot/share/runtime/reflection.cpp Wed May 30 11:36:46 2018 -0700 +++ b/src/hotspot/share/runtime/reflection.cpp Thu May 31 13:39:26 2018 -0700 @@ -337,7 +337,7 @@ THROW_0(vmSymbols::java_lang_NullPointerException()); } if (length < 0) { - THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); } if (java_lang_Class::is_primitive(element_mirror)) { Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); @@ -369,7 +369,7 @@ for (int i = 0; i < len; i++) { int d = dim_array->int_at(i); if (d < 0) { - THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); + THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", d)); } dimensions[i] = d; } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,1389 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.crypto.provider; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.Objects; +import javax.crypto.spec.ChaCha20ParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.*; +import sun.security.util.DerValue; + +/** + * Implementation of the ChaCha20 cipher, as described in RFC 7539. + * + * @since 11 + */ +abstract class ChaCha20Cipher extends CipherSpi { + // Mode constants + private static final int MODE_NONE = 0; + private static final int MODE_AEAD = 1; + + // Constants used in setting up the initial state + private static final int STATE_CONST_0 = 0x61707865; + private static final int STATE_CONST_1 = 0x3320646e; + private static final int STATE_CONST_2 = 0x79622d32; + private static final int STATE_CONST_3 = 0x6b206574; + + // The keystream block size in bytes and as integers + private static final int KEYSTREAM_SIZE = 64; + private static final int KS_SIZE_INTS = KEYSTREAM_SIZE / Integer.BYTES; + private static final int CIPHERBUF_BASE = 1024; + + // The initialization state of the cipher + private boolean initialized; + + // The mode of operation for this object + protected int mode; + + // The direction (encrypt vs. decrypt) for the data flow + private int direction; + + // Has all AAD data been provided (i.e. have we called our first update) + private boolean aadDone = false; + + // The key's encoding in bytes for this object + private byte[] keyBytes; + + // The nonce used for this object + private byte[] nonce; + + // The counter + private static final long MAX_UINT32 = 0x00000000FFFFFFFFL; + private long finalCounterValue; + private long counter; + + // Two arrays, both implemented as 16-element integer arrays: + // The base state, created at initialization time, and a working + // state which is a clone of the start state, and is then modified + // with the counter and the ChaCha20 block function. + private final int[] startState = new int[KS_SIZE_INTS]; + private final byte[] keyStream = new byte[KEYSTREAM_SIZE]; + + // The offset into the current keystream + private int keyStrOffset; + + // AEAD-related fields and constants + private static final int TAG_LENGTH = 16; + private long aadLen; + private long dataLen; + + // Have a buffer of zero padding that can be read all or in part + // by the authenticator. + private static final byte[] padBuf = new byte[TAG_LENGTH]; + + // Create a buffer for holding the AAD and Ciphertext lengths + private final byte[] lenBuf = new byte[TAG_LENGTH]; + + // The authenticator (Poly1305) when running in AEAD mode + protected String authAlgName; + private Poly1305 authenticator; + + // The underlying engine for doing the ChaCha20/Poly1305 work + private ChaChaEngine engine; + + // Use this VarHandle for converting the state elements into little-endian + // integer values for the ChaCha20 block function. + private static final VarHandle asIntLittleEndian = + MethodHandles.byteArrayViewVarHandle(int[].class, + ByteOrder.LITTLE_ENDIAN); + + // Use this VarHandle for converting the AAD and data lengths into + // little-endian long values for AEAD tag computations. + private static final VarHandle asLongLittleEndian = + MethodHandles.byteArrayViewVarHandle(long[].class, + ByteOrder.LITTLE_ENDIAN); + + // Use this for pulling in 8 bytes at a time as longs for XOR operations + private static final VarHandle asLongView = + MethodHandles.byteArrayViewVarHandle(long[].class, + ByteOrder.nativeOrder()); + + /** + * Default constructor. + */ + protected ChaCha20Cipher() { + } + + /** + * Set the mode of operation. Since this is a stream cipher, there + * is no mode of operation in the block-cipher sense of things. The + * protected {@code mode} field will only accept a value of {@code None} + * (case-insensitive). + * + * @param mode The mode value + * + * @throws NoSuchAlgorithmException if a mode of operation besides + * {@code None} is provided. + */ + @Override + protected void engineSetMode(String mode) throws NoSuchAlgorithmException { + if (mode.equalsIgnoreCase("None") == false) { + throw new NoSuchAlgorithmException("Mode must be None"); + } + } + + /** + * Set the padding scheme. Padding schemes do not make sense with stream + * ciphers, but allow {@code NoPadding}. See JCE spec. + * + * @param padding The padding type. The only allowed value is + * {@code NoPadding} case insensitive). + * + * @throws NoSuchPaddingException if a padding scheme besides + * {@code NoPadding} is provided. + */ + @Override + protected void engineSetPadding(String padding) + throws NoSuchPaddingException { + if (padding.equalsIgnoreCase("NoPadding") == false) { + throw new NoSuchPaddingException("Padding must be NoPadding"); + } + } + + /** + * Returns the block size. For a stream cipher like ChaCha20, this + * value will always be zero. + * + * @return This method always returns 0. See the JCE Specification. + */ + @Override + protected int engineGetBlockSize() { + return 0; + } + + /** + * Get the output size based on an input length. In simple stream-cipher + * mode, the output size will equal the input size. For ChaCha20-Poly1305 + * for encryption the output size will be the sum of the input length + * and tag length. For decryption, the output size will be the input + * length less the tag length or zero, whichever is larger. + * + * @param inputLen the length in bytes of the input + * + * @return the output length in bytes. + */ + @Override + protected int engineGetOutputSize(int inputLen) { + int outLen = 0; + + if (mode == MODE_NONE) { + outLen = inputLen; + } else if (mode == MODE_AEAD) { + outLen = (direction == Cipher.ENCRYPT_MODE) ? + Math.addExact(inputLen, TAG_LENGTH) : + Integer.max(inputLen - TAG_LENGTH, 0); + } + + return outLen; + } + + /** + * Get the nonce value used. + * + * @return the nonce bytes. For ChaCha20 this will be a 12-byte value. + */ + @Override + protected byte[] engineGetIV() { + return nonce.clone(); + } + + /** + * Get the algorithm parameters for this cipher. For the ChaCha20 + * cipher, this will always return {@code null} as there currently is + * no {@code AlgorithmParameters} implementation for ChaCha20. For + * ChaCha20-Poly1305, a {@code ChaCha20Poly1305Parameters} object will be + * created and initialized with the configured nonce value and returned + * to the caller. + * + * @return a {@code null} value if the ChaCha20 cipher is used (mode is + * MODE_NONE), or a {@code ChaCha20Poly1305Parameters} object containing + * the nonce if the mode is MODE_AEAD. + */ + @Override + protected AlgorithmParameters engineGetParameters() { + AlgorithmParameters params = null; + if (mode == MODE_AEAD) { + try { + // Force the 12-byte nonce into a DER-encoded OCTET_STRING + byte[] derNonce = new byte[nonce.length + 2]; + derNonce[0] = 0x04; // OCTET_STRING tag + derNonce[1] = (byte)nonce.length; // 12-byte length; + System.arraycopy(nonce, 0, derNonce, 2, nonce.length); + params = AlgorithmParameters.getInstance("ChaCha20-Poly1305"); + params.init(derNonce); + } catch (NoSuchAlgorithmException | IOException exc) { + throw new RuntimeException(exc); + } + } + + return params; + } + + /** + * Initialize the engine using a key and secure random implementation. If + * a SecureRandom object is provided it will be used to create a random + * nonce value. If the {@code random} parameter is null an internal + * secure random source will be used to create the random nonce. + * The counter value will be set to 1. + * + * @param opmode the type of operation to do. This value may not be + * {@code Cipher.DECRYPT_MODE} or {@code Cipher.UNWRAP_MODE} mode + * because it must generate random parameters like the nonce. + * @param key a 256-bit key suitable for ChaCha20 + * @param random a {@code SecureRandom} implementation used to create the + * random nonce. If {@code null} is used for the random object, + * then an internal secure random source will be used to create the + * nonce. + * + * @throws UnsupportedOperationException if the mode of operation + * is {@code Cipher.WRAP_MODE} or {@code Cipher.UNWRAP_MODE} + * (currently unsupported). + * @throws InvalidKeyException if the key is of the wrong type or is + * not 256-bits in length. This will also be thrown if the opmode + * parameter is {@code Cipher.DECRYPT_MODE}. + * {@code Cipher.UNWRAP_MODE} would normally be disallowed in this + * context but it is preempted by the UOE case above. + */ + @Override + protected void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException { + if (opmode != Cipher.DECRYPT_MODE) { + byte[] newNonce = createRandomNonce(random); + counter = 1; + init(opmode, key, newNonce); + } else { + throw new InvalidKeyException("Default parameter generation " + + "disallowed in DECRYPT and UNWRAP modes"); + } + } + + /** + * Initialize the engine using a key and secure random implementation. + * + * @param opmode the type of operation to do. This value must be either + * {@code Cipher.ENCRYPT_MODE} or {@code Cipher.DECRYPT_MODE} + * @param key a 256-bit key suitable for ChaCha20 + * @param params a {@code ChaCha20ParameterSpec} that will provide + * the nonce and initial block counter value. + * @param random a {@code SecureRandom} implementation, this parameter + * is not used in this form of the initializer. + * + * @throws UnsupportedOperationException if the mode of operation + * is {@code Cipher.WRAP_MODE} or {@code Cipher.UNWRAP_MODE} + * (currently unsupported). + * @throws InvalidKeyException if the key is of the wrong type or is + * not 256-bits in length. This will also be thrown if the opmode + * parameter is not {@code Cipher.ENCRYPT_MODE} or + * {@code Cipher.DECRYPT_MODE} (excepting the UOE case above). + * @throws InvalidAlgorithmParameterException if {@code params} is + * not a {@code ChaCha20ParameterSpec} + * @throws NullPointerException if {@code params} is {@code null} + */ + @Override + protected void engineInit(int opmode, Key key, + AlgorithmParameterSpec params, SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + + // If AlgorithmParameterSpec is null, then treat this like an init + // of the form (int, Key, SecureRandom) + if (params == null) { + engineInit(opmode, key, random); + return; + } + + // We will ignore the secure random implementation and use the nonce + // from the AlgorithmParameterSpec instead. + byte[] newNonce = null; + switch (mode) { + case MODE_NONE: + if (!(params instanceof ChaCha20ParameterSpec)) { + throw new InvalidAlgorithmParameterException( + "ChaCha20 algorithm requires ChaCha20ParameterSpec"); + } + ChaCha20ParameterSpec chaParams = (ChaCha20ParameterSpec)params; + newNonce = chaParams.getNonce(); + counter = ((long)chaParams.getCounter()) & 0x00000000FFFFFFFFL; + break; + case MODE_AEAD: + if (!(params instanceof IvParameterSpec)) { + throw new InvalidAlgorithmParameterException( + "ChaCha20-Poly1305 requires IvParameterSpec"); + } + IvParameterSpec ivParams = (IvParameterSpec)params; + newNonce = ivParams.getIV(); + if (newNonce.length != 12) { + throw new InvalidAlgorithmParameterException( + "ChaCha20-Poly1305 nonce must be 12 bytes in length"); + } + break; + default: + // Should never happen + throw new RuntimeException("ChaCha20 in unsupported mode"); + } + init(opmode, key, newNonce); + } + + /** + * Initialize the engine using the {@code AlgorithmParameter} initialization + * format. This cipher does supports initialization with + * {@code AlgorithmParameter} objects for ChaCha20-Poly1305 but not for + * ChaCha20 as a simple stream cipher. In the latter case, it will throw + * an {@code InvalidAlgorithmParameterException} if the value is non-null. + * If a null value is supplied for the {@code params} field + * the cipher will be initialized with the counter value set to 1 and + * a random nonce. If {@code null} is used for the random object, + * then an internal secure random source will be used to create the + * nonce. + * + * @param opmode the type of operation to do. This value must be either + * {@code Cipher.ENCRYPT_MODE} or {@code Cipher.DECRYPT_MODE} + * @param key a 256-bit key suitable for ChaCha20 + * @param params a {@code null} value if the algorithm is ChaCha20, or + * the appropriate {@code AlgorithmParameters} object containing the + * nonce information if the algorithm is ChaCha20-Poly1305. + * @param random a {@code SecureRandom} implementation, may be {@code null}. + * + * @throws UnsupportedOperationException if the mode of operation + * is {@code Cipher.WRAP_MODE} or {@code Cipher.UNWRAP_MODE} + * (currently unsupported). + * @throws InvalidKeyException if the key is of the wrong type or is + * not 256-bits in length. This will also be thrown if the opmode + * parameter is not {@code Cipher.ENCRYPT_MODE} or + * {@code Cipher.DECRYPT_MODE} (excepting the UOE case above). + * @throws InvalidAlgorithmParameterException if {@code params} is + * non-null and the algorithm is ChaCha20. This exception will be + * also thrown if the algorithm is ChaCha20-Poly1305 and an incorrect + * {@code AlgorithmParameters} object is supplied. + */ + @Override + protected void engineInit(int opmode, Key key, + AlgorithmParameters params, SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + + // If AlgorithmParameters is null, then treat this like an init + // of the form (int, Key, SecureRandom) + if (params == null) { + engineInit(opmode, key, random); + return; + } + + byte[] newNonce = null; + switch (mode) { + case MODE_NONE: + throw new InvalidAlgorithmParameterException( + "AlgorithmParameters not supported"); + case MODE_AEAD: + String paramAlg = params.getAlgorithm(); + if (!paramAlg.equalsIgnoreCase("ChaCha20-Poly1305")) { + throw new InvalidAlgorithmParameterException( + "Invalid parameter type: " + paramAlg); + } + try { + DerValue dv = new DerValue(params.getEncoded()); + newNonce = dv.getOctetString(); + if (newNonce.length != 12) { + throw new InvalidAlgorithmParameterException( + "ChaCha20-Poly1305 nonce must be " + + "12 bytes in length"); + } + } catch (IOException ioe) { + throw new InvalidAlgorithmParameterException(ioe); + } + break; + default: + throw new RuntimeException("Invalid mode: " + mode); + } + + // If after all the above processing we still don't have a nonce value + // then supply a random one provided a random source has been given. + if (newNonce == null) { + newNonce = createRandomNonce(random); + } + + // Continue with initialization + init(opmode, key, newNonce); + } + + /** + * Update additional authenticated data (AAD). + * + * @param src the byte array containing the authentication data. + * @param offset the starting offset in the buffer to update. + * @param len the amount of authentication data to update. + * + * @throws IllegalStateException if the cipher has not been initialized, + * {@code engineUpdate} has been called, or the cipher is running + * in a non-AEAD mode of operation. It will also throw this + * exception if the submitted AAD would overflow a 64-bit length + * counter. + */ + @Override + protected void engineUpdateAAD(byte[] src, int offset, int len) { + if (!initialized) { + // We know that the cipher has not been initialized if the key + // is still null. + throw new IllegalStateException( + "Attempted to update AAD on uninitialized Cipher"); + } else if (aadDone) { + // No AAD updates allowed after the PT/CT update method is called + throw new IllegalStateException("Attempted to update AAD on " + + "Cipher after plaintext/ciphertext update"); + } else if (mode != MODE_AEAD) { + throw new IllegalStateException( + "Cipher is running in non-AEAD mode"); + } else { + try { + aadLen = Math.addExact(aadLen, len); + authUpdate(src, offset, len); + } catch (ArithmeticException ae) { + throw new IllegalStateException("AAD overflow", ae); + } + } + } + + /** + * Update additional authenticated data (AAD). + * + * @param src the ByteBuffer containing the authentication data. + * + * @throws IllegalStateException if the cipher has not been initialized, + * {@code engineUpdate} has been called, or the cipher is running + * in a non-AEAD mode of operation. It will also throw this + * exception if the submitted AAD would overflow a 64-bit length + * counter. + */ + @Override + protected void engineUpdateAAD(ByteBuffer src) { + if (!initialized) { + // We know that the cipher has not been initialized if the key + // is still null. + throw new IllegalStateException( + "Attempted to update AAD on uninitialized Cipher"); + } else if (aadDone) { + // No AAD updates allowed after the PT/CT update method is called + throw new IllegalStateException("Attempted to update AAD on " + + "Cipher after plaintext/ciphertext update"); + } else if (mode != MODE_AEAD) { + throw new IllegalStateException( + "Cipher is running in non-AEAD mode"); + } else { + try { + aadLen = Math.addExact(aadLen, (src.limit() - src.position())); + authenticator.engineUpdate(src); + } catch (ArithmeticException ae) { + throw new IllegalStateException("AAD overflow", ae); + } + } + } + + /** + * Create a random 12-byte nonce. + * + * @param random a {@code SecureRandom} object. If {@code null} is + * provided a new {@code SecureRandom} object will be instantiated. + * + * @return a 12-byte array containing the random nonce. + */ + private byte[] createRandomNonce(SecureRandom random) { + byte[] newNonce = new byte[12]; + SecureRandom rand = (random != null) ? random : new SecureRandom(); + rand.nextBytes(newNonce); + return newNonce; + } + + /** + * Perform additional initialization actions based on the key and operation + * type. + * + * @param opmode the type of operation to do. This value must be either + * {@code Cipher.ENCRYPT_MODE} or {@code Cipher.DECRYPT_MODE} + * @param key a 256-bit key suitable for ChaCha20 + * @param newNonce the new nonce value for this initialization. + * + * @throws UnsupportedOperationException if the {@code opmode} parameter + * is {@code Cipher.WRAP_MODE} or {@code Cipher.UNWRAP_MODE} + * (currently unsupported). + * @throws InvalidKeyException if the {@code opmode} parameter is not + * {@code Cipher.ENCRYPT_MODE} or {@code Cipher.DECRYPT_MODE}, or + * if the key format is not {@code RAW}. + */ + private void init(int opmode, Key key, byte[] newNonce) + throws InvalidKeyException { + if ((opmode == Cipher.WRAP_MODE) || (opmode == Cipher.UNWRAP_MODE)) { + throw new UnsupportedOperationException( + "WRAP_MODE and UNWRAP_MODE are not currently supported"); + } else if ((opmode != Cipher.ENCRYPT_MODE) && + (opmode != Cipher.DECRYPT_MODE)) { + throw new InvalidKeyException("Unknown opmode: " + opmode); + } + + // Make sure that the provided key and nonce are unique before + // assigning them to the object. + byte[] newKeyBytes = getEncodedKey(key); + checkKeyAndNonce(newKeyBytes, newNonce); + this.keyBytes = newKeyBytes; + nonce = newNonce; + + // Now that we have the key and nonce, we can build the initial state + setInitialState(); + + if (mode == MODE_NONE) { + engine = new EngineStreamOnly(); + } else if (mode == MODE_AEAD) { + if (opmode == Cipher.ENCRYPT_MODE) { + engine = new EngineAEADEnc(); + } else if (opmode == Cipher.DECRYPT_MODE) { + engine = new EngineAEADDec(); + } else { + throw new InvalidKeyException("Not encrypt or decrypt mode"); + } + } + + // We can also get one block's worth of keystream created + finalCounterValue = counter + MAX_UINT32; + generateKeystream(); + direction = opmode; + aadDone = false; + this.keyStrOffset = 0; + initialized = true; + } + + /** + * Check the key and nonce bytes to make sure that they do not repeat + * across reinitialization. + * + * @param newKeyBytes the byte encoding for the newly provided key + * @param newNonce the new nonce to be used with this initialization + * + * @throws InvalidKeyException if both the key and nonce match the + * previous initialization. + * + */ + private void checkKeyAndNonce(byte[] newKeyBytes, byte[] newNonce) + throws InvalidKeyException { + // A new initialization must have either a different key or nonce + // so the starting state for each block is not the same as the + // previous initialization. + if (MessageDigest.isEqual(newKeyBytes, keyBytes) && + MessageDigest.isEqual(newNonce, nonce)) { + throw new InvalidKeyException( + "Matching key and nonce from previous initialization"); + } + } + + /** + * Return the encoded key as a byte array + * + * @param key the {@code Key} object used for this {@code Cipher} + * + * @return the key bytes + * + * @throws InvalidKeyException if the key is of the wrong type or length, + * or if the key encoding format is not {@code RAW}. + */ + private static byte[] getEncodedKey(Key key) throws InvalidKeyException { + if ("RAW".equals(key.getFormat()) == false) { + throw new InvalidKeyException("Key encoding format must be RAW"); + } + byte[] encodedKey = key.getEncoded(); + if (encodedKey == null || encodedKey.length != 32) { + throw new InvalidKeyException("Key length must be 256 bits"); + } + return encodedKey; + } + + /** + * Update the currently running operation with additional data + * + * @param in the plaintext or ciphertext input bytes (depending on the + * operation type). + * @param inOfs the offset into the input array + * @param inLen the length of the data to use for the update operation. + * + * @return the resulting plaintext or ciphertext bytes (depending on + * the operation type) + */ + @Override + protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) { + byte[] out = new byte[inLen]; + try { + engine.doUpdate(in, inOfs, inLen, out, 0); + } catch (ShortBufferException | KeyException exc) { + throw new RuntimeException(exc); + } + + return out; + } + + /** + * Update the currently running operation with additional data + * + * @param in the plaintext or ciphertext input bytes (depending on the + * operation type). + * @param inOfs the offset into the input array + * @param inLen the length of the data to use for the update operation. + * @param out the byte array that will hold the resulting data. The array + * must be large enough to hold the resulting data. + * @param outOfs the offset for the {@code out} buffer to begin writing + * the resulting data. + * + * @return the length in bytes of the data written into the {@code out} + * buffer. + * + * @throws ShortBufferException if the buffer {@code out} does not have + * enough space to hold the resulting data. + */ + @Override + protected int engineUpdate(byte[] in, int inOfs, int inLen, + byte[] out, int outOfs) throws ShortBufferException { + int bytesUpdated = 0; + try { + bytesUpdated = engine.doUpdate(in, inOfs, inLen, out, outOfs); + } catch (KeyException ke) { + throw new RuntimeException(ke); + } + return bytesUpdated; + } + + /** + * Complete the currently running operation using any final + * data provided by the caller. + * + * @param in the plaintext or ciphertext input bytes (depending on the + * operation type). + * @param inOfs the offset into the input array + * @param inLen the length of the data to use for the update operation. + * + * @return the resulting plaintext or ciphertext bytes (depending on + * the operation type) + * + * @throws AEADBadTagException if, during decryption, the provided tag + * does not match the calculated tag. + */ + @Override + protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen) + throws AEADBadTagException { + byte[] output = new byte[engineGetOutputSize(inLen)]; + try { + engine.doFinal(in, inOfs, inLen, output, 0); + } catch (ShortBufferException | KeyException exc) { + throw new RuntimeException(exc); + } finally { + // Regardless of what happens, the cipher cannot be used for + // further processing until it has been freshly initialized. + initialized = false; + } + return output; + } + + /** + * Complete the currently running operation using any final + * data provided by the caller. + * + * @param in the plaintext or ciphertext input bytes (depending on the + * operation type). + * @param inOfs the offset into the input array + * @param inLen the length of the data to use for the update operation. + * @param out the byte array that will hold the resulting data. The array + * must be large enough to hold the resulting data. + * @param outOfs the offset for the {@code out} buffer to begin writing + * the resulting data. + * + * @return the length in bytes of the data written into the {@code out} + * buffer. + * + * @throws ShortBufferException if the buffer {@code out} does not have + * enough space to hold the resulting data. + * @throws AEADBadTagException if, during decryption, the provided tag + * does not match the calculated tag. + */ + @Override + protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, + int outOfs) throws ShortBufferException, AEADBadTagException { + + int bytesUpdated = 0; + try { + bytesUpdated = engine.doFinal(in, inOfs, inLen, out, outOfs); + } catch (KeyException ke) { + throw new RuntimeException(ke); + } finally { + // Regardless of what happens, the cipher cannot be used for + // further processing until it has been freshly initialized. + initialized = false; + } + return bytesUpdated; + } + + /** + * Wrap a {@code Key} using this Cipher's current encryption parameters. + * + * @param key the key to wrap. The data that will be encrypted will + * be the provided {@code Key} in its encoded form. + * + * @return a byte array consisting of the wrapped key. + * + * @throws UnsupportedOperationException this will (currently) always + * be thrown, as this method is not currently supported. + */ + @Override + protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, + InvalidKeyException { + throw new UnsupportedOperationException( + "Wrap operations are not supported"); + } + + /** + * Unwrap a {@code Key} using this Cipher's current encryption parameters. + * + * @param wrappedKey the key to unwrap. + * @param algorithm the algorithm associated with the wrapped key + * @param type the type of the wrapped key. This is one of + * {@code SECRET_KEY}, {@code PRIVATE_KEY}, or {@code PUBLIC_KEY}. + * + * @return the unwrapped key as a {@code Key} object. + * + * @throws UnsupportedOperationException this will (currently) always + * be thrown, as this method is not currently supported. + */ + @Override + protected Key engineUnwrap(byte[] wrappedKey, String algorithm, + int type) throws InvalidKeyException, NoSuchAlgorithmException { + throw new UnsupportedOperationException( + "Unwrap operations are not supported"); + } + + /** + * Get the length of a provided key in bits. + * + * @param key the key to be evaluated + * + * @return the length of the key in bits + * + * @throws InvalidKeyException if the key is invalid or does not + * have an encoded form. + */ + @Override + protected int engineGetKeySize(Key key) throws InvalidKeyException { + byte[] encodedKey = getEncodedKey(key); + return encodedKey.length << 3; + } + + /** + * Set the initial state. This will populate the state array and put the + * key and nonce into their proper locations. The counter field is not + * set here. + * + * @throws IllegalArgumentException if the key or nonce are not in + * their proper lengths (32 bytes for the key, 12 bytes for the + * nonce). + * @throws InvalidKeyException if the key does not support an encoded form. + */ + private void setInitialState() throws InvalidKeyException { + // Apply constants to first 4 words + startState[0] = STATE_CONST_0; + startState[1] = STATE_CONST_1; + startState[2] = STATE_CONST_2; + startState[3] = STATE_CONST_3; + + // Apply the key bytes as 8 32-bit little endian ints (4 through 11) + for (int i = 0; i < 32; i += 4) { + startState[(i / 4) + 4] = (keyBytes[i] & 0x000000FF) | + ((keyBytes[i + 1] << 8) & 0x0000FF00) | + ((keyBytes[i + 2] << 16) & 0x00FF0000) | + ((keyBytes[i + 3] << 24) & 0xFF000000); + } + + startState[12] = 0; + + // The final integers for the state are from the nonce + // interpreted as 3 little endian integers + for (int i = 0; i < 12; i += 4) { + startState[(i / 4) + 13] = (nonce[i] & 0x000000FF) | + ((nonce[i + 1] << 8) & 0x0000FF00) | + ((nonce[i + 2] << 16) & 0x00FF0000) | + ((nonce[i + 3] << 24) & 0xFF000000); + } + } + + /** + * Using the current state and counter create the next set of keystream + * bytes. This method will generate the next 512 bits of keystream and + * return it in the {@code keyStream} parameter. Following the + * block function the counter will be incremented. + */ + private void generateKeystream() { + chaCha20Block(startState, counter, keyStream); + counter++; + } + + /** + * Perform a full 20-round ChaCha20 transform on the initial state. + * + * @param initState the starting state, not including the counter + * value. + * @param counter the counter value to apply + * @param result the array that will hold the result of the ChaCha20 + * block function. + * + * @note it is the caller's responsibility to ensure that the workState + * is sized the same as the initState, no checking is performed internally. + */ + private static void chaCha20Block(int[] initState, long counter, + byte[] result) { + // Create an initial state and clone a working copy + int ws00 = STATE_CONST_0; + int ws01 = STATE_CONST_1; + int ws02 = STATE_CONST_2; + int ws03 = STATE_CONST_3; + int ws04 = initState[4]; + int ws05 = initState[5]; + int ws06 = initState[6]; + int ws07 = initState[7]; + int ws08 = initState[8]; + int ws09 = initState[9]; + int ws10 = initState[10]; + int ws11 = initState[11]; + int ws12 = (int)counter; + int ws13 = initState[13]; + int ws14 = initState[14]; + int ws15 = initState[15]; + + // Peform 10 iterations of the 8 quarter round set + for (int round = 0; round < 10; round++) { + ws00 += ws04; + ws12 = Integer.rotateLeft(ws12 ^ ws00, 16); + + ws08 += ws12; + ws04 = Integer.rotateLeft(ws04 ^ ws08, 12); + + ws00 += ws04; + ws12 = Integer.rotateLeft(ws12 ^ ws00, 8); + + ws08 += ws12; + ws04 = Integer.rotateLeft(ws04 ^ ws08, 7); + + ws01 += ws05; + ws13 = Integer.rotateLeft(ws13 ^ ws01, 16); + + ws09 += ws13; + ws05 = Integer.rotateLeft(ws05 ^ ws09, 12); + + ws01 += ws05; + ws13 = Integer.rotateLeft(ws13 ^ ws01, 8); + + ws09 += ws13; + ws05 = Integer.rotateLeft(ws05 ^ ws09, 7); + + ws02 += ws06; + ws14 = Integer.rotateLeft(ws14 ^ ws02, 16); + + ws10 += ws14; + ws06 = Integer.rotateLeft(ws06 ^ ws10, 12); + + ws02 += ws06; + ws14 = Integer.rotateLeft(ws14 ^ ws02, 8); + + ws10 += ws14; + ws06 = Integer.rotateLeft(ws06 ^ ws10, 7); + + ws03 += ws07; + ws15 = Integer.rotateLeft(ws15 ^ ws03, 16); + + ws11 += ws15; + ws07 = Integer.rotateLeft(ws07 ^ ws11, 12); + + ws03 += ws07; + ws15 = Integer.rotateLeft(ws15 ^ ws03, 8); + + ws11 += ws15; + ws07 = Integer.rotateLeft(ws07 ^ ws11, 7); + + ws00 += ws05; + ws15 = Integer.rotateLeft(ws15 ^ ws00, 16); + + ws10 += ws15; + ws05 = Integer.rotateLeft(ws05 ^ ws10, 12); + + ws00 += ws05; + ws15 = Integer.rotateLeft(ws15 ^ ws00, 8); + + ws10 += ws15; + ws05 = Integer.rotateLeft(ws05 ^ ws10, 7); + + ws01 += ws06; + ws12 = Integer.rotateLeft(ws12 ^ ws01, 16); + + ws11 += ws12; + ws06 = Integer.rotateLeft(ws06 ^ ws11, 12); + + ws01 += ws06; + ws12 = Integer.rotateLeft(ws12 ^ ws01, 8); + + ws11 += ws12; + ws06 = Integer.rotateLeft(ws06 ^ ws11, 7); + + ws02 += ws07; + ws13 = Integer.rotateLeft(ws13 ^ ws02, 16); + + ws08 += ws13; + ws07 = Integer.rotateLeft(ws07 ^ ws08, 12); + + ws02 += ws07; + ws13 = Integer.rotateLeft(ws13 ^ ws02, 8); + + ws08 += ws13; + ws07 = Integer.rotateLeft(ws07 ^ ws08, 7); + + ws03 += ws04; + ws14 = Integer.rotateLeft(ws14 ^ ws03, 16); + + ws09 += ws14; + ws04 = Integer.rotateLeft(ws04 ^ ws09, 12); + + ws03 += ws04; + ws14 = Integer.rotateLeft(ws14 ^ ws03, 8); + + ws09 += ws14; + ws04 = Integer.rotateLeft(ws04 ^ ws09, 7); + } + + // Add the end working state back into the original state + asIntLittleEndian.set(result, 0, ws00 + STATE_CONST_0); + asIntLittleEndian.set(result, 4, ws01 + STATE_CONST_1); + asIntLittleEndian.set(result, 8, ws02 + STATE_CONST_2); + asIntLittleEndian.set(result, 12, ws03 + STATE_CONST_3); + asIntLittleEndian.set(result, 16, ws04 + initState[4]); + asIntLittleEndian.set(result, 20, ws05 + initState[5]); + asIntLittleEndian.set(result, 24, ws06 + initState[6]); + asIntLittleEndian.set(result, 28, ws07 + initState[7]); + asIntLittleEndian.set(result, 32, ws08 + initState[8]); + asIntLittleEndian.set(result, 36, ws09 + initState[9]); + asIntLittleEndian.set(result, 40, ws10 + initState[10]); + asIntLittleEndian.set(result, 44, ws11 + initState[11]); + // Add the counter back into workState[12] + asIntLittleEndian.set(result, 48, ws12 + (int)counter); + asIntLittleEndian.set(result, 52, ws13 + initState[13]); + asIntLittleEndian.set(result, 56, ws14 + initState[14]); + asIntLittleEndian.set(result, 60, ws15 + initState[15]); + } + + /** + * Perform the ChaCha20 transform. + * + * @param in the array of bytes for the input + * @param inOff the offset into the input array to start the transform + * @param inLen the length of the data to perform the transform on. + * @param out the output array. It must be large enough to hold the + * resulting data + * @param outOff the offset into the output array to place the resulting + * data. + */ + private void chaCha20Transform(byte[] in, int inOff, int inLen, + byte[] out, int outOff) throws KeyException { + int remainingData = inLen; + + while (remainingData > 0) { + int ksRemain = keyStream.length - keyStrOffset; + if (ksRemain <= 0) { + if (counter <= finalCounterValue) { + generateKeystream(); + keyStrOffset = 0; + ksRemain = keyStream.length; + } else { + throw new KeyException("Counter exhausted. " + + "Reinitialize with new key and/or nonce"); + } + } + + // XOR each byte in the keystream against the input + int xformLen = Math.min(remainingData, ksRemain); + xor(keyStream, keyStrOffset, in, inOff, out, outOff, xformLen); + outOff += xformLen; + inOff += xformLen; + keyStrOffset += xformLen; + remainingData -= xformLen; + } + } + + private static void xor(byte[] in1, int off1, byte[] in2, int off2, + byte[] out, int outOff, int len) { + while (len >= 8) { + long v1 = (long) asLongView.get(in1, off1); + long v2 = (long) asLongView.get(in2, off2); + asLongView.set(out, outOff, v1 ^ v2); + off1 += 8; + off2 += 8; + outOff += 8; + len -= 8; + } + while (len > 0) { + out[outOff] = (byte) (in1[off1] ^ in2[off2]); + off1++; + off2++; + outOff++; + len--; + } + } + + /** + * Perform initialization steps for the authenticator + * + * @throws InvalidKeyException if the key is unusable for some reason + * (invalid length, etc.) + */ + private void initAuthenticator() throws InvalidKeyException { + authenticator = new Poly1305(); + + // Derive the Poly1305 key from the starting state + byte[] serializedKey = new byte[KEYSTREAM_SIZE]; + chaCha20Block(startState, 0, serializedKey); + + authenticator.engineInit(new SecretKeySpec(serializedKey, 0, 32, + authAlgName), null); + aadLen = 0; + dataLen = 0; + } + + /** + * Update the authenticator state with data. This routine can be used + * to add data to the authenticator, whether AAD or application data. + * + * @param data the data to stir into the authenticator. + * @param offset the offset into the data. + * @param length the length of data to add to the authenticator. + * + * @return the number of bytes processed by this method. + */ + private int authUpdate(byte[] data, int offset, int length) { + Objects.checkFromIndexSize(offset, length, data.length); + authenticator.engineUpdate(data, offset, length); + return length; + } + + /** + * Finalize the data and return the tag. + * + * @param data an array containing any remaining data to process. + * @param dataOff the offset into the data. + * @param length the length of the data to process. + * @param out the array to write the resulting tag into + * @param outOff the offset to begin writing the data. + * + * @throws ShortBufferException if there is insufficient room to + * write the tag. + */ + private void authFinalizeData(byte[] data, int dataOff, int length, + byte[] out, int outOff) throws ShortBufferException { + // Update with the final chunk of ciphertext, then pad to a + // multiple of 16. + if (data != null) { + dataLen += authUpdate(data, dataOff, length); + } + authPad16(dataLen); + + // Also write the AAD and ciphertext data lengths as little-endian + // 64-bit values. + authWriteLengths(aadLen, dataLen, lenBuf); + authenticator.engineUpdate(lenBuf, 0, lenBuf.length); + byte[] tag = authenticator.engineDoFinal(); + Objects.checkFromIndexSize(outOff, tag.length, out.length); + System.arraycopy(tag, 0, out, outOff, tag.length); + aadLen = 0; + dataLen = 0; + } + + /** + * Based on a given length of data, make the authenticator process + * zero bytes that will pad the length out to a multiple of 16. + * + * @param dataLen the starting length to be padded. + */ + private void authPad16(long dataLen) { + // Pad out the AAD or data to a multiple of 16 bytes + authenticator.engineUpdate(padBuf, 0, + (TAG_LENGTH - ((int)dataLen & 15)) & 15); + } + + /** + * Write the two 64-bit little-endian length fields into an array + * for processing by the poly1305 authenticator. + * + * @param aLen the length of the AAD. + * @param dLen the length of the application data. + * @param buf the buffer to write the two lengths into. + * + * @note it is the caller's responsibility to provide an array large + * enough to hold the two longs. + */ + private void authWriteLengths(long aLen, long dLen, byte[] buf) { + asLongLittleEndian.set(buf, 0, aLen); + asLongLittleEndian.set(buf, Long.BYTES, dLen); + } + + /** + * Interface for the underlying processing engines for ChaCha20 + */ + interface ChaChaEngine { + /** + * Perform a multi-part update for ChaCha20. + * + * @param in the input data. + * @param inOff the offset into the input. + * @param inLen the length of the data to process. + * @param out the output buffer. + * @param outOff the offset at which to write the output data. + * + * @return the number of output bytes written. + * + * @throws ShortBufferException if the output buffer does not + * provide enough space. + * @throws KeyException if the counter value has been exhausted. + */ + int doUpdate(byte[] in, int inOff, int inLen, byte[] out, int outOff) + throws ShortBufferException, KeyException; + + /** + * Finalize a multi-part or single-part ChaCha20 operation. + * + * @param in the input data. + * @param inOff the offset into the input. + * @param inLen the length of the data to process. + * @param out the output buffer. + * @param outOff the offset at which to write the output data. + * + * @return the number of output bytes written. + * + * @throws ShortBufferException if the output buffer does not + * provide enough space. + * @throws AEADBadTagException if in decryption mode the provided + * tag and calculated tag do not match. + * @throws KeyException if the counter value has been exhausted. + */ + int doFinal(byte[] in, int inOff, int inLen, byte[] out, int outOff) + throws ShortBufferException, AEADBadTagException, KeyException; + } + + private final class EngineStreamOnly implements ChaChaEngine { + + private EngineStreamOnly () { } + + @Override + public int doUpdate(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws ShortBufferException, KeyException { + if (initialized) { + try { + if (out != null) { + Objects.checkFromIndexSize(outOff, inLen, out.length); + } else { + throw new ShortBufferException( + "Output buffer too small"); + } + } catch (IndexOutOfBoundsException iobe) { + throw new ShortBufferException("Output buffer too small"); + } + if (in != null) { + Objects.checkFromIndexSize(inOff, inLen, in.length); + chaCha20Transform(in, inOff, inLen, out, outOff); + } + return inLen; + } else { + throw new IllegalStateException( + "Must use either a different key or iv."); + } + } + + @Override + public int doFinal(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws ShortBufferException, KeyException { + return doUpdate(in, inOff, inLen, out, outOff); + } + } + + private final class EngineAEADEnc implements ChaChaEngine { + + private EngineAEADEnc() throws InvalidKeyException { + initAuthenticator(); + counter = 1; + } + + @Override + public int doUpdate(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws ShortBufferException, KeyException { + if (initialized) { + // If this is the first update since AAD updates, signal that + // we're done processing AAD info and pad the AAD to a multiple + // of 16 bytes. + if (!aadDone) { + authPad16(aadLen); + aadDone = true; + } + try { + if (out != null) { + Objects.checkFromIndexSize(outOff, inLen, out.length); + } else { + throw new ShortBufferException( + "Output buffer too small"); + } + } catch (IndexOutOfBoundsException iobe) { + throw new ShortBufferException("Output buffer too small"); + } + if (in != null) { + Objects.checkFromIndexSize(inOff, inLen, in.length); + chaCha20Transform(in, inOff, inLen, out, outOff); + dataLen += authUpdate(out, outOff, inLen); + } + + return inLen; + } else { + throw new IllegalStateException( + "Must use either a different key or iv."); + } + } + + @Override + public int doFinal(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws ShortBufferException, KeyException { + // Make sure we have enough room for the remaining data (if any) + // and the tag. + if ((inLen + TAG_LENGTH) > (out.length - outOff)) { + throw new ShortBufferException("Output buffer too small"); + } + + doUpdate(in, inOff, inLen, out, outOff); + authFinalizeData(null, 0, 0, out, outOff + inLen); + aadDone = false; + return inLen + TAG_LENGTH; + } + } + + private final class EngineAEADDec implements ChaChaEngine { + + private final ByteArrayOutputStream cipherBuf; + private final byte[] tag; + + private EngineAEADDec() throws InvalidKeyException { + initAuthenticator(); + counter = 1; + cipherBuf = new ByteArrayOutputStream(CIPHERBUF_BASE); + tag = new byte[TAG_LENGTH]; + } + + @Override + public int doUpdate(byte[] in, int inOff, int inLen, byte[] out, + int outOff) { + if (initialized) { + // If this is the first update since AAD updates, signal that + // we're done processing AAD info and pad the AAD to a multiple + // of 16 bytes. + if (!aadDone) { + authPad16(aadLen); + aadDone = true; + } + + if (in != null) { + Objects.checkFromIndexSize(inOff, inLen, in.length); + cipherBuf.write(in, inOff, inLen); + } + } else { + throw new IllegalStateException( + "Must use either a different key or iv."); + } + + return 0; + } + + @Override + public int doFinal(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws ShortBufferException, AEADBadTagException, + KeyException { + + byte[] ctPlusTag; + int ctPlusTagLen; + if (cipherBuf.size() == 0 && inOff == 0) { + // No previous data has been seen before doFinal, so we do + // not need to hold any ciphertext in a buffer. We can + // process it directly from the "in" parameter. + doUpdate(null, inOff, inLen, out, outOff); + ctPlusTag = in; + ctPlusTagLen = inLen; + } else { + doUpdate(in, inOff, inLen, out, outOff); + ctPlusTag = cipherBuf.toByteArray(); + ctPlusTagLen = ctPlusTag.length; + } + cipherBuf.reset(); + + // There must at least be a tag length's worth of ciphertext + // data in the buffered input. + if (ctPlusTagLen < TAG_LENGTH) { + throw new AEADBadTagException("Input too short - need tag"); + } + int ctLen = ctPlusTagLen - TAG_LENGTH; + + // Make sure we will have enough room for the output buffer + try { + Objects.checkFromIndexSize(outOff, ctLen, out.length); + } catch (IndexOutOfBoundsException ioobe) { + throw new ShortBufferException("Output buffer too small"); + } + + // Calculate and compare the tag. Only do the decryption + // if and only if the tag matches. + authFinalizeData(ctPlusTag, 0, ctLen, tag, 0); + if (Arrays.compare(ctPlusTag, ctLen, ctPlusTagLen, + tag, 0, tag.length) != 0) { + throw new AEADBadTagException("Tag mismatch"); + } + chaCha20Transform(ctPlusTag, 0, ctLen, out, outOff); + aadDone = false; + + return ctLen; + } + } + + public static final class ChaCha20Only extends ChaCha20Cipher { + public ChaCha20Only() { + mode = MODE_NONE; + } + } + + public static final class ChaCha20Poly1305 extends ChaCha20Cipher { + public ChaCha20Poly1305() { + mode = MODE_AEAD; + authAlgName = "Poly1305"; + } + } +} diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Poly1305Parameters.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Poly1305Parameters.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.crypto.provider; + +import java.io.IOException; +import java.security.AlgorithmParametersSpi; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import javax.crypto.spec.IvParameterSpec; +import sun.security.util.*; + +/** + * This class implements the parameter set used with the ChaCha20-Poly1305 + * algorithm. The parameter definition comes from + * RFC 8103 + * and is defined according to the following ASN.1: + * + *
+ * id-alg-AEADChaCha20Poly1305 OBJECT IDENTIFIER ::=
+          { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
+            pkcs9(9) smime(16) alg(3) 18 }
+
+ * AEADChaCha20Poly1305Nonce ::= OCTET STRING (SIZE(12))
+ * 
+ * + * The AlgorithmParameters may be instantiated either by its name + * ("ChaCha20-Poly1305") or via its OID (1.2.840.113549.1.9.16.3.18) + */ +public final class ChaCha20Poly1305Parameters extends AlgorithmParametersSpi { + + private static final String DEFAULT_FMT = "ASN.1"; + private byte[] nonce; + + public ChaCha20Poly1305Parameters() {} + + /** + * Initialize the ChaCha20Poly1305Parameters using an IvParameterSpec. + * + * @param paramSpec the {@code IvParameterSpec} used to configure + * this object. + * + * @throws InvalidParameterSpecException if an object of a type other + * than {@code IvParameterSpec} is used. + */ + @Override + protected void engineInit(AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException { + + if (!(paramSpec instanceof IvParameterSpec)) { + throw new InvalidParameterSpecException + ("Inappropriate parameter specification"); + } + IvParameterSpec ivps = (IvParameterSpec)paramSpec; + + // Obtain the nonce + nonce = ivps.getIV(); + if (nonce.length != 12) { + throw new InvalidParameterSpecException("ChaCha20-Poly1305 nonce" + + " must be 12 bytes in length"); + } + } + + /** + * Initialize the ChaCha20Poly1305Parameters from a DER encoded + * parameter block. + + * @param encoded the DER encoding of the nonce as an OCTET STRING. + * + * @throws IOException if the encoded nonce is not 12 bytes long or a DER + * decoding error occurs. + */ + @Override + protected void engineInit(byte[] encoded) throws IOException { + DerValue val = new DerValue(encoded); + + // Get the nonce value + nonce = val.getOctetString(); + if (nonce.length != 12) { + throw new IOException( + "ChaCha20-Poly1305 nonce must be 12 bytes in length"); + } + } + + /** + * Initialize the ChaCha20Poly1305Parameters from a DER encoded + * parameter block. + * + * @param encoded the DER encoding of the nonce and initial block counter. + * @param decodingMethod the decoding method. The only currently accepted + * value is "ASN.1" + * + * @throws IOException if the encoded nonce is not 12 bytes long, a DER + * decoding error occurs, or an unsupported decoding method is + * provided. + */ + @Override + protected void engineInit(byte[] encoded, String decodingMethod) + throws IOException { + if (decodingMethod == null || + decodingMethod.equalsIgnoreCase(DEFAULT_FMT)) { + engineInit(encoded); + } else { + throw new IOException("Unsupported parameter format: " + + decodingMethod); + } + } + + /** + * Return an IvParameterSpec with the same parameters as those + * held in this object. + * + * @param paramSpec the class name of the spec. In this case it should + * be {@code IvParameterSpec.class}. + * + * @return a {@code IvParameterSpec} object containing the nonce + * value held in this object. + * + * @throws InvalidParameterSpecException if a class other than + * {@code IvParameterSpec.class} was specified in the paramSpec + * parameter. + */ + @Override + protected + T engineGetParameterSpec(Class paramSpec) + throws InvalidParameterSpecException { + + if (IvParameterSpec.class.isAssignableFrom(paramSpec)) { + return paramSpec.cast(new IvParameterSpec(nonce)); + } else { + throw new InvalidParameterSpecException + ("Inappropriate parameter specification"); + } + } + + /** + * Return the encoded parameters in ASN.1 form. + * + * @return a byte array containing the DER-encoding for the + * ChaCha20-Poly1305 parameters. This will be the nonce + * encoded as a DER OCTET STRING. + * + * @throws IOException if any DER encoding error occurs. + */ + @Override + protected byte[] engineGetEncoded() throws IOException { + DerOutputStream out = new DerOutputStream(); + out.write(DerValue.tag_OctetString, nonce); + return out.toByteArray(); + } + + /** + * Return the encoded parameters in ASN.1 form. + * + * @param encodingMethod the encoding method to be used. This parameter + * must be "ASN.1" as it is the only currently supported encoding + * format. If the parameter is {@code null} then the default + * encoding format will be used. + * + * @return a byte array containing the DER-encoding for the + * ChaCha20-Poly1305 parameters. + * + * @throws IOException if any DER encoding error occurs or an unsupported + * encoding method is provided. + */ + @Override + protected byte[] engineGetEncoded(String encodingMethod) + throws IOException { + if (encodingMethod == null || + encodingMethod.equalsIgnoreCase(DEFAULT_FMT)) { + return engineGetEncoded(); + } else { + throw new IOException("Unsupported encoding format: " + + encodingMethod); + } + } + + /** + * Creates a formatted string describing the parameters. + * + * @return a string representation of the ChaCha20 parameters. + */ + @Override + protected String engineToString() { + String LINE_SEP = System.lineSeparator(); + HexDumpEncoder encoder = new HexDumpEncoder(); + StringBuilder sb = new StringBuilder(LINE_SEP + "nonce:" + + LINE_SEP + "[" + encoder.encodeBuffer(nonce) + "]"); + return sb.toString(); + } +} diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,16 +111,20 @@ protected HmacSHA2KG(String algoName, int len) { core = new KeyGeneratorCore(algoName, len); } + @Override protected void engineInit(SecureRandom random) { core.implInit(random); } + @Override protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { core.implInit(params, random); } + @Override protected void engineInit(int keySize, SecureRandom random) { core.implInit(keySize, random); } + @Override protected SecretKey engineGenerateKey() { return core.implGenerateKey(); } @@ -153,13 +157,16 @@ public RC2KeyGenerator() { core = new KeyGeneratorCore("RC2", 128); } + @Override protected void engineInit(SecureRandom random) { core.implInit(random); } + @Override protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { core.implInit(params, random); } + @Override protected void engineInit(int keySize, SecureRandom random) { if ((keySize < 40) || (keySize > 1024)) { throw new InvalidParameterException("Key length for RC2" @@ -167,6 +174,7 @@ } core.implInit(keySize, random); } + @Override protected SecretKey engineGenerateKey() { return core.implGenerateKey(); } @@ -178,13 +186,16 @@ public ARCFOURKeyGenerator() { core = new KeyGeneratorCore("ARCFOUR", 128); } + @Override protected void engineInit(SecureRandom random) { core.implInit(random); } + @Override protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { core.implInit(params, random); } + @Override protected void engineInit(int keySize, SecureRandom random) { if ((keySize < 40) || (keySize > 1024)) { throw new InvalidParameterException("Key length for ARCFOUR" @@ -192,9 +203,38 @@ } core.implInit(keySize, random); } + @Override protected SecretKey engineGenerateKey() { return core.implGenerateKey(); } } + // nested static class for the ChaCha20 key generator + public static final class ChaCha20KeyGenerator extends KeyGeneratorSpi { + private final KeyGeneratorCore core; + public ChaCha20KeyGenerator() { + core = new KeyGeneratorCore("ChaCha20", 256); + } + @Override + protected void engineInit(SecureRandom random) { + core.implInit(random); + } + @Override + protected void engineInit(AlgorithmParameterSpec params, + SecureRandom random) throws InvalidAlgorithmParameterException { + core.implInit(params, random); + } + @Override + protected void engineInit(int keySize, SecureRandom random) { + if (keySize != 256) { + throw new InvalidParameterException( + "Key length for ChaCha20 must be 256 bits"); + } + core.implInit(keySize, random); + } + @Override + protected SecretKey engineGenerateKey() { + return core.implGenerateKey(); + } + } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/com/sun/crypto/provider/Poly1305.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/Poly1305.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.crypto.provider; + +import java.nio.ByteBuffer; +import java.security.Key; +import java.security.InvalidKeyException; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.Objects; + +import sun.security.util.math.*; +import sun.security.util.math.intpoly.*; + +/** + * This class represents the Poly1305 function defined in RFC 7539. + * + * This function is used in the implementation of ChaCha20/Poly1305 + * AEAD mode. + */ +final class Poly1305 { + + private static final int KEY_LENGTH = 32; + private static final int RS_LENGTH = KEY_LENGTH / 2; + private static final int BLOCK_LENGTH = 16; + private static final int TAG_LENGTH = 16; + + private static final IntegerFieldModuloP ipl1305 = + new IntegerPolynomial1305(); + + private byte[] keyBytes; + private final byte[] block = new byte[BLOCK_LENGTH]; + private int blockOffset; + + private IntegerModuloP r; + private IntegerModuloP s; + private MutableIntegerModuloP a; + private final MutableIntegerModuloP n = ipl1305.get1().mutable(); + + Poly1305() { } + + /** + * Initialize the Poly1305 object + * + * @param newKey the {@code Key} which will be used for the authentication. + * @param params this parameter is unused. + * + * @throws InvalidKeyException if {@code newKey} is {@code null} or is + * not 32 bytes in length. + */ + void engineInit(Key newKey, AlgorithmParameterSpec params) + throws InvalidKeyException { + Objects.requireNonNull(newKey, "Null key provided during init"); + keyBytes = newKey.getEncoded(); + if (keyBytes == null) { + throw new InvalidKeyException("Key does not support encoding"); + } else if (keyBytes.length != KEY_LENGTH) { + throw new InvalidKeyException("Incorrect length for key: " + + keyBytes.length); + } + + engineReset(); + setRSVals(); + } + + /** + * Returns the length of the MAC (authentication tag). + * + * @return the length of the auth tag, which is always 16 bytes. + */ + int engineGetMacLength() { + return TAG_LENGTH; + } + + /** + * Reset the Poly1305 object, discarding any current operation but + * maintaining the same key. + */ + void engineReset() { + // Clear the block and reset the offset + Arrays.fill(block, (byte)0); + blockOffset = 0; + // Discard any previous accumulator and start at zero + a = ipl1305.get0().mutable(); + } + + /** + * Update the MAC with bytes from a {@code ByteBuffer} + * + * @param buf the {@code ByteBuffer} containing the data to be consumed. + * Upon return the buffer's position will be equal to its limit. + */ + void engineUpdate(ByteBuffer buf) { + int remaining = buf.remaining(); + while (remaining > 0) { + int bytesToWrite = Integer.min(remaining, + BLOCK_LENGTH - blockOffset); + + if (bytesToWrite >= BLOCK_LENGTH) { + // If bytes to write == BLOCK_LENGTH, then we have no + // left-over data from previous updates and we can create + // the IntegerModuloP directly from the input buffer. + processBlock(buf, bytesToWrite); + } else { + // We have some left-over data from previous updates, so + // copy that into the holding block until we get a full block. + buf.get(block, blockOffset, bytesToWrite); + blockOffset += bytesToWrite; + + if (blockOffset >= BLOCK_LENGTH) { + processBlock(block, 0, BLOCK_LENGTH); + blockOffset = 0; + } + } + + remaining -= bytesToWrite; + } + } + + /** + * Update the MAC with bytes from an array. + * + * @param input the input bytes. + * @param offset the starting index from which to update the MAC. + * @param len the number of bytes to process. + */ + void engineUpdate(byte[] input, int offset, int len) { + Objects.checkFromIndexSize(offset, len, input.length); + if (blockOffset > 0) { + // We have some left-over data from previous updates + int blockSpaceLeft = BLOCK_LENGTH - blockOffset; + if (len < blockSpaceLeft) { + System.arraycopy(input, offset, block, blockOffset, len); + blockOffset += len; + return; // block wasn't filled + } else { + System.arraycopy(input, offset, block, blockOffset, + blockSpaceLeft); + offset += blockSpaceLeft; + len -= blockSpaceLeft; + processBlock(block, 0, BLOCK_LENGTH); + blockOffset = 0; + } + } + while (len >= BLOCK_LENGTH) { + processBlock(input, offset, BLOCK_LENGTH); + offset += BLOCK_LENGTH; + len -= BLOCK_LENGTH; + } + if (len > 0) { // and len < BLOCK_LENGTH + System.arraycopy(input, offset, block, 0, len); + blockOffset = len; + } + } + + /** + * Update the MAC with a single byte of input + * + * @param input the byte to update the MAC with. + */ + void engineUpdate(byte input) { + assert (blockOffset < BLOCK_LENGTH); + // we can't hold fully filled unprocessed block + block[blockOffset++] = input; + + if (blockOffset == BLOCK_LENGTH) { + processBlock(block, 0, BLOCK_LENGTH); + blockOffset = 0; + } + } + + + /** + * Finish the authentication operation and reset the MAC for a new + * authentication operation. + * + * @return the authentication tag as a byte array. + */ + byte[] engineDoFinal() { + byte[] tag = new byte[BLOCK_LENGTH]; + + // Finish up: process any remaining data < BLOCK_SIZE, then + // create the tag from the resulting little-endian integer. + if (blockOffset > 0) { + processBlock(block, 0, blockOffset); + blockOffset = 0; + } + + // Add in the s-half of the key to the accumulator + a.addModPowerTwo(s, tag); + + // Reset for the next auth + engineReset(); + return tag; + } + + /** + * Process a single block of data. This should only be called + * when the block array is complete. That may not necessarily + * be a full 16 bytes if the last block has less than 16 bytes. + */ + private void processBlock(ByteBuffer buf, int len) { + n.setValue(buf, len, (byte)0x01); + a.setSum(n); // a += (n | 0x01) + a.setProduct(r); // a = (a * r) % p + } + + private void processBlock(byte[] block, int offset, int length) { + Objects.checkFromIndexSize(offset, length, block.length); + n.setValue(block, offset, length, (byte)0x01); + a.setSum(n); // a += (n | 0x01) + a.setProduct(r); // a = (a * r) % p + } + + /** + * Partition the authentication key into the R and S components, clamp + * the R value, and instantiate IntegerModuloP objects to R and S's + * numeric values. + */ + private void setRSVals() { + // Clamp the bytes in the "r" half of the key. + keyBytes[3] &= 15; + keyBytes[7] &= 15; + keyBytes[11] &= 15; + keyBytes[15] &= 15; + keyBytes[4] &= 252; + keyBytes[8] &= 252; + keyBytes[12] &= 252; + + // Create IntegerModuloP elements from the r and s values + r = ipl1305.getElement(keyBytes, 0, RS_LENGTH, (byte)0); + s = ipl1305.getElement(keyBytes, RS_LENGTH, RS_LENGTH, (byte)0); + } +} diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Thu May 31 13:39:26 2018 -0700 @@ -57,6 +57,8 @@ * * - ARCFOUR (RC4 compatible) * + * - ChaCha20 (Stream cipher only and in AEAD mode with Poly1305) + * * - Cipher modes ECB, CBC, CFB, OFB, PCBC, CTR, and CTS for all block ciphers * and mode GCM for AES cipher * @@ -77,7 +79,7 @@ private static final String info = "SunJCE Provider " + "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, " - + "Diffie-Hellman, HMAC)"; + + "Diffie-Hellman, HMAC, ChaCha20)"; private static final String OID_PKCS12_RC4_128 = "1.2.840.113549.1.12.1.1"; private static final String OID_PKCS12_RC4_40 = "1.2.840.113549.1.12.1.2"; @@ -336,6 +338,15 @@ put("Cipher.ARCFOUR SupportedPaddings", "NOPADDING"); put("Cipher.ARCFOUR SupportedKeyFormats", "RAW"); + put("Cipher.ChaCha20", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only"); + put("Cipher.ChaCha20 SupportedKeyFormats", "RAW"); + put("Cipher.ChaCha20-Poly1305", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305"); + put("Cipher.ChaCha20-Poly1305 SupportedKeyFormats", "RAW"); + put("Alg.Alias.Cipher.1.2.840.113549.1.9.16.3.18", "ChaCha20-Poly1305"); + put("Alg.Alias.Cipher.OID.1.2.840.113549.1.9.16.3.18", "ChaCha20-Poly1305"); + /* * Key(pair) Generator engines */ @@ -361,6 +372,10 @@ "ARCFOURKeyGenerator"); put("Alg.Alias.KeyGenerator.RC4", "ARCFOUR"); + put("KeyGenerator.ChaCha20", + "com.sun.crypto.provider.KeyGeneratorCore$" + + "ChaCha20KeyGenerator"); + put("KeyGenerator.HmacMD5", "com.sun.crypto.provider.HmacMD5KeyGenerator"); @@ -541,6 +556,9 @@ put("AlgorithmParameters.OAEP", "com.sun.crypto.provider.OAEPParameters"); + put("AlgorithmParameters.ChaCha20-Poly1305", + "com.sun.crypto.provider.ChaCha20Poly1305Parameters"); + /* * Key factories */ diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/java/lang/Character.java --- a/src/java.base/share/classes/java/lang/Character.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/java/lang/Character.java Thu May 31 13:39:26 2018 -0700 @@ -1419,7 +1419,8 @@ "YIRADICALS"); /** - * Constant for the "Cyrillic Supplementary" Unicode character block. + * Constant for the "Cyrillic Supplement" Unicode character block. + * This block was previously known as the "Cyrillic Supplementary" block. * @since 1.5 */ public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java --- a/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java Thu May 31 13:39:26 2018 -0700 @@ -134,6 +134,8 @@ String recipe = (String)argv[0]; Object[] shiftedArgs = Arrays.copyOfRange(argv, 1, argv.length); result = (CallSite)bootstrapMethod.invokeExact(caller, name, (MethodType)type, recipe, shiftedArgs); + } else if (isLambdaMetafactoryAltMetafactoryBSM(bsmType)) { + result = (CallSite)bootstrapMethod.invokeExact(caller, name, (MethodType)type, argv); } else { switch (argv.length) { case 0: @@ -286,6 +288,9 @@ private static final MethodType LMF_INDY_MT = MethodType.methodType(CallSite.class, Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + private static final MethodType LMF_ALT_MT = MethodType.methodType(CallSite.class, + Lookup.class, String.class, MethodType.class, Object[].class); + private static final MethodType LMF_CONDY_MT = MethodType.methodType(Object.class, Lookup.class, String.class, Class.class, MethodType.class, MethodHandle.class, MethodType.class); @@ -319,6 +324,15 @@ return bsmType == LMF_INDY_MT; } + /** + * @return true iff the BSM method type exactly matches + * {@see java.lang.invoke.LambdaMetafactory#altMetafactory( + * MethodHandles.Lookup,String,MethodType,Object[])} + */ + private static boolean isLambdaMetafactoryAltMetafactoryBSM(MethodType bsmType) { + return bsmType == LMF_ALT_MT; + } + /** The JVM produces java.lang.Integer values to box * CONSTANT_Integer boxes but does not intern them. * Let's intern them. This is slightly wrong for diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/java/lang/invoke/MethodHandles.java --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu May 31 13:39:26 2018 -0700 @@ -3483,6 +3483,11 @@ * @return a method handle which inserts an additional argument, * before calling the original method handle * @throws NullPointerException if the target or the {@code values} array is null + * @throws IllegalArgumentException if (@code pos) is less than {@code 0} or greater than + * {@code N - L} where {@code N} is the arity of the target method handle and {@code L} + * is the length of the values array. + * @throws ClassCastException if an argument does not match the corresponding bound parameter + * type. * @see MethodHandle#bindTo */ public static diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/java/lang/ref/ReferenceQueue.java --- a/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java Thu May 31 13:39:26 2018 -0700 @@ -43,17 +43,17 @@ */ public ReferenceQueue() { } - private static class Null extends ReferenceQueue { - boolean enqueue(Reference r) { + private static class Null extends ReferenceQueue { + boolean enqueue(Reference r) { return false; } } - static ReferenceQueue NULL = new Null<>(); - static ReferenceQueue ENQUEUED = new Null<>(); + static final ReferenceQueue NULL = new Null(); + static final ReferenceQueue ENQUEUED = new Null(); private static class Lock { }; - private Lock lock = new Lock(); + private final Lock lock = new Lock(); private volatile Reference head; private long queueLength = 0; diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/java/util/function/Predicate.java --- a/src/java.base/share/classes/java/util/function/Predicate.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/java/util/function/Predicate.java Thu May 31 13:39:26 2018 -0700 @@ -116,4 +116,20 @@ ? Objects::isNull : object -> targetRef.equals(object); } + + /** + * Returns a predicate that is the negation of the supplied predicate. + * + * @param the type of arguments to the specified predicate + * @param target predicate to negate + * + * @return a predicate that negates the results of the supplied + * predicate + * + * @since 11 + */ + @SuppressWarnings("unchecked") + static Predicate not(Predicate target) { + return (Predicate)target.negate(); + } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/javax/crypto/Cipher.java --- a/src/java.base/share/classes/javax/crypto/Cipher.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/javax/crypto/Cipher.java Thu May 31 13:39:26 2018 -0700 @@ -111,7 +111,7 @@ * encryption with a given key. When IVs are repeated for GCM * encryption, such usages are subject to forgery attacks. Thus, after * each encryption operation using GCM mode, callers should re-initialize - * the cipher objects with GCM parameters which has a different IV value. + * the cipher objects with GCM parameters which have a different IV value. *
  *     GCMParameterSpec s = ...;
  *     cipher.init(..., s);
@@ -131,6 +131,13 @@
  *     ...
  *
  * 
+ * The ChaCha20 and ChaCha20-Poly1305 algorithms have a similar requirement + * for unique nonces with a given key. After each encryption or decryption + * operation, callers should re-initialize their ChaCha20 or ChaCha20-Poly1305 + * ciphers with parameters that specify a different nonce value. Please + * see RFC 7539 for more + * information on the ChaCha20 and ChaCha20-Poly1305 algorithms. + *

* Every implementation of the Java platform is required to support * the following standard {@code Cipher} transformations with the keysizes * in parentheses: diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/javax/crypto/spec/ChaCha20ParameterSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/javax/crypto/spec/ChaCha20ParameterSpec.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.crypto.spec; + +import java.security.spec.AlgorithmParameterSpec; +import java.util.Objects; + +/** + * This class specifies the parameters used with the + * ChaCha20 + * algorithm. + * + *

The parameters consist of a 12-byte nonce and an initial + * counter value expressed as a 32-bit integer. + * + *

This class can be used to initialize a {@code Cipher} object that + * implements the ChaCha20 algorithm. + * + * @since 11 + */ +public final class ChaCha20ParameterSpec implements AlgorithmParameterSpec { + + // The nonce length is defined by the spec as 96 bits (12 bytes) in length. + private static final int NONCE_LENGTH = 12; + + private final byte[] nonce; + private final int counter; + + /** + * Constructs a parameter set for ChaCha20 from the given nonce + * and counter. + * + * @param nonce a 12-byte nonce value + * @param counter the initial counter value + * + * @throws NullPointerException if {@code nonce} is {@code null} + * @throws IllegalArgumentException if {@code nonce} is not 12 bytes + * in length + */ + public ChaCha20ParameterSpec(byte[] nonce, int counter) { + this.counter = counter; + + Objects.requireNonNull(nonce, "Nonce must be non-null"); + this.nonce = nonce.clone(); + if (this.nonce.length != NONCE_LENGTH) { + throw new IllegalArgumentException( + "Nonce must be 12-bytes in length"); + } + } + + /** + * Returns the nonce value. + * + * @return the nonce value. This method returns a new array each time + * this method is called. + */ + public byte[] getNonce() { + return nonce.clone(); + } + + /** + * Returns the configured counter value. + * + * @return the counter value + */ + public int getCounter() { + return counter; + } +} diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java --- a/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.net.SocketOption; import java.util.Collections; import java.util.Set; +import java.util.stream.Collectors; /** * Defines the infrastructure to support extended socket options, beyond those @@ -40,6 +41,9 @@ */ public abstract class ExtendedSocketOptions { + public static final short SOCK_STREAM = 1; + public static final short SOCK_DGRAM = 2; + private final Set> options; /** Tells whether or not the option is supported. */ @@ -50,6 +54,30 @@ /** Return the, possibly empty, set of extended socket options available. */ public final Set> options() { return options; } + public static final Set> options(short type) { + return getInstance().options0(type); + } + + private Set> options0(short type) { + Set> extOptions = null; + switch (type) { + case SOCK_DGRAM: + extOptions = options.stream() + .filter((option) -> !option.name().startsWith("TCP_")) + .collect(Collectors.toUnmodifiableSet()); + break; + case SOCK_STREAM: + extOptions = options.stream() + .filter((option) -> !option.name().startsWith("UDP_")) + .collect(Collectors.toUnmodifiableSet()); + break; + default: + //this will never happen + throw new IllegalArgumentException("Invalid socket option type"); + } + return extOptions; + } + /** Sets the value of a socket option, for the given socket. */ public abstract void setOption(FileDescriptor fd, SocketOption option, Object value) throws SocketException; diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,8 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import sun.net.NetHooks; +import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM; /** * Base implementation of AsynchronousServerSocketChannel. @@ -234,6 +236,7 @@ if (Net.isReusePortAvailable()) { set.add(StandardSocketOptions.SO_REUSEPORT); } + set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); return Collections.unmodifiableSet(set); } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import java.util.concurrent.locks.*; import sun.net.NetHooks; import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM; /** * Base implementation of AsynchronousSocketChannel @@ -512,9 +513,7 @@ set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.TCP_NODELAY); - ExtendedSocketOptions extendedOptions = - ExtendedSocketOptions.getInstance(); - set.addAll(extendedOptions.options()); + set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); return Collections.unmodifiableSet(set); } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu May 31 13:39:26 2018 -0700 @@ -57,6 +57,7 @@ import sun.net.ResourceManager; import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_DGRAM; /** * An implementation of DatagramChannels. @@ -334,7 +335,7 @@ set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); - set.addAll(ExtendedSocketOptions.getInstance().options()); + set.addAll(ExtendedSocketOptions.options(SOCK_DGRAM)); return Collections.unmodifiableSet(set); } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Thu May 31 13:39:26 2018 -0700 @@ -49,6 +49,8 @@ import java.util.concurrent.locks.ReentrantLock; import sun.net.NetHooks; +import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM; /** * An implementation of ServerSocketChannels @@ -199,6 +201,7 @@ set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.IP_TOS); + set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); return Collections.unmodifiableSet(set); } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Thu May 31 13:39:26 2018 -0700 @@ -54,6 +54,7 @@ import sun.net.NetHooks; import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM; /** * An implementation of SocketChannels @@ -280,7 +281,7 @@ // additional options required by socket adaptor set.add(StandardSocketOptions.IP_TOS); set.add(ExtendedSocketOption.SO_OOBINLINE); - set.addAll(ExtendedSocketOptions.getInstance().options()); + set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); return Collections.unmodifiableSet(set); } } diff -r d66751750b72 -r c10dbcaed048 src/java.base/share/lib/security/cacerts Binary file src/java.base/share/lib/security/cacerts has changed diff -r d66751750b72 -r c10dbcaed048 src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java --- a/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.util.Set; import java.util.HashSet; import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_DGRAM; /* * On Unix systems we simply delegate to native methods. @@ -77,18 +78,10 @@ protected Set> supportedOptions() { HashSet> options = new HashSet<>(super.supportedOptions()); - addExtSocketOptions(extendedOptions.options(), options); + options.addAll(ExtendedSocketOptions.options(SOCK_DGRAM)); return options; } - private void addExtSocketOptions(Set> extOptions, - Set> options) { - // TCP_QUICKACK is applicable for TCP Sockets only. - extOptions.stream() - .filter((option) -> !option.name().equals("TCP_QUICKACK")) - .forEach((option) -> options.add(option)); - } - protected void socketSetOption(int opt, Object val) throws SocketException { if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { diff -r d66751750b72 -r c10dbcaed048 src/java.base/unix/classes/java/net/PlainSocketImpl.java --- a/src/java.base/unix/classes/java/net/PlainSocketImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.util.Set; import java.util.HashSet; import sun.net.ext.ExtendedSocketOptions; +import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM; /* * On Unix systems we simply delegate to native methods. @@ -90,7 +91,7 @@ protected Set> supportedOptions() { HashSet> options = new HashSet<>(super.supportedOptions()); - addExtSocketOptions(extendedOptions.options(), options); + addExtSocketOptions(ExtendedSocketOptions.options(SOCK_STREAM), options); return options; } diff -r d66751750b72 -r c10dbcaed048 src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java --- a/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java Thu May 31 13:39:26 2018 -0700 @@ -99,6 +99,25 @@ * mechanism provider. The application will need to ensure that it has the * appropriate permissions if such checks are made in the mechanism layer.

* + * The stream-based methods of {@code GSSContext} have been deprecated in + * Java SE 11. These methods have also been removed from + * + * RFC 8353: Generic Security Service API Version 2: Java Bindings Update + * for the following reasons (see section 11): "The overloaded methods of + * GSSContext that use input and output streams as the means to convey + * authentication and per-message GSS-API tokens as described in Section 5.15 + * of RFC 5653 are removed in this update as the wire protocol + * should be defined by an application and not a library. It's also impossible + * to implement these methods correctly when the token has no self-framing + * (where the end cannot be determined), or the library has no knowledge of + * the token format (for example, as a bridge talking to another GSS library)". + * These methods include {@link #initSecContext(InputStream, OutputStream)}, + * {@link #acceptSecContext(InputStream, OutputStream)}, + * {@link #wrap(InputStream, OutputStream, MessageProp)}, + * {@link #unwrap(InputStream, OutputStream, MessageProp)}, + * {@link #getMIC(InputStream, OutputStream, MessageProp)}, + * and {@link #verifyMIC(InputStream, InputStream, MessageProp)}.

+ * * The example code presented below demonstrates the usage of the * GSSContext interface for the initiating peer. Different * operations on the GSSContext object are presented, @@ -316,7 +335,10 @@ * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, * {@link GSSException#FAILURE GSSException.FAILURE} + * @deprecated The stream-based methods have been removed from RFC 8353. + * Use {@link #initSecContext(byte[], int, int)} instead. */ + @Deprecated(since="11") public int initSecContext(InputStream inStream, OutputStream outStream) throws GSSException; @@ -459,6 +481,9 @@ * {@link GSSException#DUPLICATE_TOKEN GSSException.DUPLICATE_TOKEN}, * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, * {@link GSSException#FAILURE GSSException.FAILURE} + * + * @deprecated The stream-based methods have been removed from RFC 8353. + * Use {@link #acceptSecContext(byte[], int, int)} instead. */ /* Missing return value in RFC. int should have been returned. * ----------------------------------------------------------- @@ -472,6 +497,7 @@ * 0 indicates that no token needs to be * sent. */ + @Deprecated(since="11") public void acceptSecContext(InputStream inStream, OutputStream outStream) throws GSSException; @@ -613,7 +639,11 @@ * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, * {@link GSSException#FAILURE GSSException.FAILURE} + * + * @deprecated The stream-based methods have been removed from RFC 8353. + * Use {@link #wrap(byte[], int, int, MessageProp)} instead. */ + @Deprecated(since="11") public void wrap(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException; @@ -696,7 +726,11 @@ * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, * {@link GSSException#FAILURE GSSException.FAILURE} + * + * @deprecated The stream-based methods have been removed from RFC 8353. + * Use {@link #unwrap(byte[], int, int, MessageProp)} instead. */ + @Deprecated(since="11") public void unwrap(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException; @@ -761,7 +795,11 @@ * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, * {@link GSSException#FAILURE GSSException.FAILURE} + * + * @deprecated The stream-based methods have been removed from RFC 8353. + * Use {@link #getMIC(byte[], int, int, MessageProp)} instead. */ + @Deprecated(since="11") public void getMIC(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException; @@ -844,7 +882,12 @@ * {@link GSSException#BAD_MIC GSSException.BAD_MIC} * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED} * {@link GSSException#FAILURE GSSException.FAILURE} + * + * @deprecated The stream-based methods have been removed from RFC 8353. + * Use {@link #verifyMIC(byte[], int, int, byte[], int, int, MessageProp)} + * instead. */ + @Deprecated(since="11") public void verifyMIC(InputStream tokStream, InputStream msgStream, MessageProp msgProp) throws GSSException; diff -r d66751750b72 -r c10dbcaed048 src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java --- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java Thu May 31 13:39:26 2018 -0700 @@ -197,6 +197,7 @@ return (size == 0? null : bos.toByteArray()); } + @Deprecated(since="11") public int initSecContext(InputStream inStream, OutputStream outStream) throws GSSException { @@ -305,6 +306,7 @@ return (out.length == 0) ? null : out; } + @Deprecated(since="11") public void acceptSecContext(InputStream inStream, OutputStream outStream) throws GSSException { @@ -405,6 +407,7 @@ "No mechanism context yet!"); } + @Deprecated(since="11") public void wrap(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException { if (mechCtxt != null) @@ -423,6 +426,7 @@ "No mechanism context yet!"); } + @Deprecated(since="11") public void unwrap(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException { if (mechCtxt != null) @@ -441,6 +445,7 @@ "No mechanism context yet!"); } + @Deprecated(since="11") public void getMIC(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException { if (mechCtxt != null) @@ -461,6 +466,7 @@ "No mechanism context yet!"); } + @Deprecated(since="11") public void verifyMIC(InputStream tokStream, InputStream msgStream, MessageProp msgProp) throws GSSException { if (mechCtxt != null) diff -r d66751750b72 -r c10dbcaed048 src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java --- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Wed May 30 11:36:46 2018 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Thu May 31 13:39:26 2018 -0700 @@ -281,6 +281,7 @@ * to its peer for processing. * @exception GSSException */ + @Deprecated(since="11") public final byte[] initSecContext(InputStream is, int mechTokenSize) throws GSSException { @@ -475,6 +476,7 @@ * to its peer for processing. * @exception GSSException */ + @Deprecated(since="11") public final byte[] acceptSecContext(InputStream is, int mechTokenSize) throws GSSException { @@ -1128,6 +1130,7 @@ } } + @Deprecated(since="11") public final void wrap(InputStream is, OutputStream os, MessageProp msgProp) throws GSSException { if (mechContext != null) { @@ -1149,6 +1152,7 @@ } } + @Deprecated(since="11") public final void unwrap(InputStream is, OutputStream os, MessageProp msgProp) throws GSSException { if (mechContext != null) { @@ -1170,6 +1174,7 @@ } } + @Deprecated(since="11") public final void getMIC(InputStream is, OutputStream os, MessageProp msgProp) throws GSSException { if (mechContext != null) { @@ -1193,6 +1198,7 @@ } } + @Deprecated(since="11") public final void verifyMIC(InputStream is, InputStream msgStr, MessageProp msgProp) throws GSSException { if (mechContext != null) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu May 31 13:39:26 2018 -0700 @@ -139,7 +139,7 @@ CompilationResult compilationResult = new CompilationResult(id, isImmutablePIC); return GraalCompiler.compileGraph(graph, resolvedMethod, providers, backend, graphBuilderSuite, OptimisticOptimizations.ALL, profilingInfo, getSuites(), getLirSuites(), - compilationResult, CompilationResultBuilderFactory.Default); + compilationResult, CompilationResultBuilderFactory.Default, true); } catch (Throwable e) { main.handleError(resolvedMethod, e, " (compiling graph)"); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -63,11 +63,15 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FMSUB; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FMUL; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FNEG; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FRINTM; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FRINTN; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FRINTP; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FRINTZ; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FSQRT; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FSUB; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.HINT; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.HLT; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDADD; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDAR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDAXR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDP; @@ -480,6 +484,9 @@ private static final int CASAcquireOffset = 22; private static final int CASReleaseOffset = 15; + private static final int LDADDAcquireOffset = 23; + private static final int LDADDReleaseOffset = 22; + /** * Encoding for all instructions. */ @@ -511,6 +518,7 @@ STP(0b0 << 22), CAS(0x08A07C00), + LDADD(0x38200000), ADR(0x00000000), ADRP(0x80000000), @@ -573,6 +581,9 @@ FSQRT(0x00018000), FNEG(0x00010000), + FRINTM(0x00050000), + FRINTN(0x00040000), + FRINTP(0x00048000), FRINTZ(0x00058000), FADD(0x00002000), @@ -1330,7 +1341,18 @@ emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt)); } - /* Compare And Swap */ + /** + * Compare And Swap word or doubleword in memory. This reads a value from an address rn, + * compares it against a given value rs, and, if equal, stores the value rt to memory. The value + * read from address rn is stored in register rs. + * + * @param size size of bits read from memory. Must be 32 or 64. + * @param rs general purpose register to be compared and loaded. May not be null. + * @param rt general purpose register to be conditionally stored. May not be null. + * @param rn general purpose register containing the address from which to read. + * @param acquire boolean value signifying if the load should use acquire semantics. + * @param release boolean value signifying if the store should use release semantics. + */ public void cas(int size, Register rs, Register rt, Register rn, boolean acquire, boolean release) { assert size == 32 || size == 64; int transferSize = NumUtil.log2Ceil(size / 8); @@ -1344,17 +1366,42 @@ emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt) | (acquire ? 1 : 0) << CASAcquireOffset | (release ? 1 : 0) << CASReleaseOffset); } + /** + * Atomic add. This reads a value from an address rn, stores the value in rt, and adds the value + * in rs to it, and stores the result back at address rn. The initial value read from memory is + * stored in rt. + * + * @param size size of operand to read from memory. Must be 8, 16, 32, or 64. + * @param rs general purpose register to be added to contents. May not be null. + * @param rt general purpose register to be loaded. May not be null. + * @param rn general purpose register or stack pointer holding an address from which to load. + * @param acquire boolean value signifying if the load should use acquire semantics. + * @param release boolean value signifying if the store should use release semantics. + */ + public void ldadd(int size, Register rs, Register rt, Register rn, boolean acquire, boolean release) { + assert size == 8 || size == 16 || size == 32 || size == 64; + int transferSize = NumUtil.log2Ceil(size / 8); + loadAndAddInstruction(LDADD, rs, rt, rn, transferSize, acquire, release); + } + + private void loadAndAddInstruction(Instruction instr, Register rs, Register rt, Register rn, int log2TransferSize, boolean acquire, boolean release) { + assert log2TransferSize >= 0 && log2TransferSize < 4; + assert rt.getRegisterCategory().equals(CPU) && rs.getRegisterCategory().equals(CPU) && !rs.equals(rt); + int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset; + emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt) | (acquire ? 1 : 0) << LDADDAcquireOffset | (release ? 1 : 0) << LDADDReleaseOffset); + } + /* PC-relative Address Calculation (5.4.4) */ /** * Address of page: sign extends 21-bit offset, shifts if left by 12 and adds it to the value of - * the PC with its bottom 12-bits cleared, writing the result to dst. - * No offset is emiited; the instruction will be patched later. + * the PC with its bottom 12-bits cleared, writing the result to dst. No offset is emitted; the + * instruction will be patched later. * * @param dst general purpose register. May not be null, zero-register or stackpointer. */ public void adrp(Register dst) { - emitInt(ADRP.encoding | PcRelImmOp | rd(dst) ); + emitInt(ADRP.encoding | PcRelImmOp | rd(dst)); } /** @@ -1367,14 +1414,17 @@ emitInt(ADR.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(imm21)); } + /** + * Adds a 21-bit signed offset to the program counter and writes the result to dst. + * + * @param dst general purpose register. May not be null, zero-register or stackpointer. + * @param imm21 Signed 21-bit offset. + * @param pos the position in the code that the instruction is emitted. + */ public void adr(Register dst, int imm21, int pos) { emitInt(ADR.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(imm21), pos); } - public void adrp(Register dst, int pageOffset) { - emitInt(ADRP.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(pageOffset)); - } - private static int getPcRelativeImmEncoding(int imm21) { assert NumUtil.isSignedNbit(21, imm21); int imm = imm21 & NumUtil.getNbitNumberInt(21); @@ -2432,6 +2482,39 @@ fpDataProcessing1Source(FRINTZ, dst, src, floatFromSize(size)); } + /** + * Rounds floating-point to integral. Rounds towards nearest with ties to even. + * + * @param size register size. + * @param dst floating point register. May not be null. + * @param src floating point register. May not be null. + */ + public void frintn(int size, Register dst, Register src) { + fpDataProcessing1Source(FRINTN, dst, src, floatFromSize(size)); + } + + /** + * Rounds floating-point to integral. Rounds towards minus infinity. + * + * @param size register size. + * @param dst floating point register. May not be null. + * @param src floating point register. May not be null. + */ + public void frintm(int size, Register dst, Register src) { + fpDataProcessing1Source(FRINTM, dst, src, floatFromSize(size)); + } + + /** + * Rounds floating-point to integral. Rounds towards plus infinity. + * + * @param size register size. + * @param dst floating point register. May not be null. + * @param src floating point register. May not be null. + */ + public void frintp(int size, Register dst, Register src) { + fpDataProcessing1Source(FRINTP, dst, src, floatFromSize(size)); + } + /* Floating-point Arithmetic (1 source) (5.7.6) */ /** diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Thu May 31 13:39:26 2018 -0700 @@ -1,6 +1,5 @@ /* * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +37,6 @@ import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.aarch64.AArch64.zr; -import org.graalvm.compiler.asm.AbstractAddress; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; @@ -307,9 +305,10 @@ case EXTENDED_REGISTER_OFFSET: add(64, dst, address.getBase(), address.getOffset(), address.getExtendType(), address.isScaled() ? shiftAmt : 0); break; - case PC_LITERAL: - super.adr(dst, address.getImmediateRaw()); + case PC_LITERAL: { + addressOf(dst); break; + } case BASE_REGISTER_ONLY: movx(dst, address.getBase()); break; @@ -1561,7 +1560,7 @@ } @Override - public AbstractAddress getPlaceholder(int instructionStartPosition) { + public AArch64Address getPlaceholder(int instructionStartPosition) { return AArch64Address.PLACEHOLDER; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Thu May 31 13:39:26 2018 -0700 @@ -1853,9 +1853,36 @@ CMP.getMIOpcode(DWORD, isByte(imm32)).emit(this, DWORD, dst, imm32); } - // The 32-bit cmpxchg compares the value at adr with the contents of X86.rax, - // and stores reg into adr if so; otherwise, the value at adr is loaded into X86.rax,. - // The ZF is set if the compared values were equal, and cleared otherwise. + /** + * The 8-bit cmpxchg compares the value at adr with the contents of X86.rax, and stores reg into + * adr if so; otherwise, the value at adr is loaded into X86.rax,. The ZF is set if the compared + * values were equal, and cleared otherwise. + */ + public final void cmpxchgb(Register reg, AMD64Address adr) { // cmpxchg + prefix(adr, reg); + emitByte(0x0F); + emitByte(0xB0); + emitOperandHelper(reg, adr, 0); + } + + /** + * The 16-bit cmpxchg compares the value at adr with the contents of X86.rax, and stores reg + * into adr if so; otherwise, the value at adr is loaded into X86.rax,. The ZF is set if the + * compared values were equal, and cleared otherwise. + */ + public final void cmpxchgw(Register reg, AMD64Address adr) { // cmpxchg + emitByte(0x66); // Switch to 16-bit mode. + prefix(adr, reg); + emitByte(0x0F); + emitByte(0xB1); + emitOperandHelper(reg, adr, 0); + } + + /** + * The 32-bit cmpxchg compares the value at adr with the contents of X86.rax, and stores reg + * into adr if so; otherwise, the value at adr is loaded into X86.rax,. The ZF is set if the + * compared values were equal, and cleared otherwise. + */ public final void cmpxchgl(Register reg, AMD64Address adr) { // cmpxchg prefix(adr, reg); emitByte(0x0F); @@ -3677,6 +3704,21 @@ emitByte(imm8); } + public final void xaddb(AMD64Address dst, Register src) { + prefix(dst, src); + emitByte(0x0F); + emitByte(0xC0); + emitOperandHelper(src, dst, 0); + } + + public final void xaddw(AMD64Address dst, Register src) { + emitByte(0x66); // Switch to 16-bit mode. + prefix(dst, src); + emitByte(0x0F); + emitByte(0xC1); + emitOperandHelper(src, dst, 0); + } + public final void xaddl(AMD64Address dst, Register src) { prefix(dst, src); emitByte(0x0F); @@ -3691,6 +3733,19 @@ emitOperandHelper(src, dst, 0); } + public final void xchgb(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x86); + emitOperandHelper(dst, src, 0); + } + + public final void xchgw(Register dst, AMD64Address src) { + emitByte(0x66); + prefix(src, dst); + emitByte(0x87); + emitOperandHelper(dst, src, 0); + } + public final void xchgl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x87); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecodes.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecodes.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecodes.java Thu May 31 13:39:26 2018 -0700 @@ -837,4 +837,27 @@ assert !isConditionalBranch(opcode) || isBranch(opcode) : "a conditional branch must also be a branch"; } + + public static boolean isIfBytecode(int bytecode) { + switch (bytecode) { + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + case IFNULL: + case IFNONNULL: + return true; + } + return false; + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Thu May 31 13:39:26 2018 -0700 @@ -32,9 +32,9 @@ import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ; import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.ConstantValue; @@ -491,4 +491,23 @@ throw GraalError.unimplemented(); } + @Override + public Value emitRound(Value value, RoundingMode mode) { + AArch64ArithmeticOp op; + switch (mode) { + case NEAREST: + op = AArch64ArithmeticOp.FRINTN; + break; + case UP: + op = AArch64ArithmeticOp.FRINTP; + break; + case DOWN: + op = AArch64ArithmeticOp.FRINTM; + break; + default: + throw GraalError.shouldNotReachHere(); + } + + return emitUnary(op, value); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Thu May 31 13:39:26 2018 -0700 @@ -52,6 +52,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64Move; +import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndAddOp; import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp; import org.graalvm.compiler.lir.aarch64.AArch64PauseOp; @@ -127,7 +128,7 @@ } @Override - public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { Variable prevValue = newVariable(expectedValue.getValueKind()); Variable scratch = newVariable(LIRKind.value(AArch64Kind.DWORD)); append(new CompareAndSwapOp(prevValue, loadReg(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); @@ -138,7 +139,7 @@ } @Override - public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + public Variable emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue) { Variable result = newVariable(newValue.getValueKind()); Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); append(new CompareAndSwapOp(result, loadNonCompareConst(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); @@ -146,6 +147,16 @@ } @Override + public Value emitAtomicReadAndAdd(Value address, ValueKind kind, Value delta) { + Variable result = newVariable(kind); + Variable scratch1 = newVariable(kind); + Variable scratch2 = newVariable(kind); + + append(new AtomicReadAndAddOp((AArch64Kind) kind.getPlatformKind(), asAllocatable(result), asAllocatable(address), asAllocatable(delta), asAllocatable(scratch1), asAllocatable(scratch2))); + return result; + } + + @Override public void emitMembar(int barriers) { int necessaryBarriers = target().arch.requiredBarriers(barriers); if (target().isMP && necessaryBarriers != 0) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Thu May 31 13:39:26 2018 -0700 @@ -23,13 +23,16 @@ package org.graalvm.compiler.core.amd64; +import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PS; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; @@ -190,36 +193,68 @@ } } - @Override - public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + private AllocatableValue asAllocatable(Value value, ValueKind kind) { + if (value.getValueKind().equals(kind)) { + return asAllocatable(value); + } else if (isRegister(value)) { + return asRegister(value).asValue(kind); + } else if (isConstantValue(value)) { + return emitLoadConstant(kind, asConstant(value)); + } else { + Variable variable = newVariable(kind); + emitMove(variable, value); + return variable; + } + } + + private Value emitCompareAndSwap(boolean isLogic, LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); - AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); AMD64AddressValue addressValue = asAddressValue(address); - RegisterValue raxRes = AMD64.rax.asValue(kind); - emitMove(raxRes, expectedValue); - append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue))); + LIRKind integralAccessKind = accessKind; + Value reinterpretedExpectedValue = expectedValue; + Value reinterpretedNewValue = newValue; + boolean isXmm = ((AMD64Kind) accessKind.getPlatformKind()).isXMM(); + if (isXmm) { + if (accessKind.getPlatformKind().equals(AMD64Kind.SINGLE)) { + integralAccessKind = LIRKind.fromJavaKind(target().arch, JavaKind.Int); + } else { + integralAccessKind = LIRKind.fromJavaKind(target().arch, JavaKind.Long); + } + reinterpretedExpectedValue = arithmeticLIRGen.emitReinterpret(integralAccessKind, expectedValue); + reinterpretedNewValue = arithmeticLIRGen.emitReinterpret(integralAccessKind, newValue); + } + AMD64Kind memKind = (AMD64Kind) integralAccessKind.getPlatformKind(); + RegisterValue aRes = AMD64.rax.asValue(integralAccessKind); + AllocatableValue allocatableNewValue = asAllocatable(reinterpretedNewValue, integralAccessKind); + emitMove(aRes, reinterpretedExpectedValue); + append(new CompareAndSwapOp(memKind, aRes, addressValue, aRes, allocatableNewValue)); - assert trueValue.getValueKind().equals(falseValue.getValueKind()); - Variable result = newVariable(trueValue.getValueKind()); - append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue)); - return result; + if (isLogic) { + assert trueValue.getValueKind().equals(falseValue.getValueKind()); + Variable result = newVariable(trueValue.getValueKind()); + append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue)); + return result; + } else { + if (isXmm) { + return arithmeticLIRGen.emitReinterpret(accessKind, aRes); + } else { + Variable result = newVariable(kind); + emitMove(result, aRes); + return result; + } + } } @Override - public Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { - ValueKind kind = newValue.getValueKind(); - assert kind.equals(expectedValue.getValueKind()); - AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + return (Variable) emitCompareAndSwap(true, accessKind, address, expectedValue, newValue, trueValue, falseValue); + } - AMD64AddressValue addressValue = asAddressValue(address); - RegisterValue raxRes = AMD64.rax.asValue(kind); - emitMove(raxRes, expectedValue); - append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue))); - Variable result = newVariable(kind); - emitMove(result, raxRes); - return result; + @Override + public Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue) { + return emitCompareAndSwap(false, accessKind, address, expectedValue, newValue, null, null); } public void emitCompareAndSwapBranch(ValueKind kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel, @@ -235,8 +270,7 @@ } @Override - public Value emitAtomicReadAndAdd(Value address, Value delta) { - ValueKind kind = delta.getValueKind(); + public Value emitAtomicReadAndAdd(Value address, ValueKind kind, Value delta) { Variable result = newVariable(kind); AMD64AddressValue addressValue = asAddressValue(address); append(new AMD64Move.AtomicReadAndAddOp((AMD64Kind) kind.getPlatformKind(), result, addressValue, asAllocatable(delta))); @@ -244,8 +278,7 @@ } @Override - public Value emitAtomicReadAndWrite(Value address, Value newValue) { - ValueKind kind = newValue.getValueKind(); + public Value emitAtomicReadAndWrite(Value address, ValueKind kind, Value newValue) { Variable result = newVariable(kind); AMD64AddressValue addressValue = asAddressValue(address); append(new AMD64Move.AtomicReadAndWriteOp((AMD64Kind) kind.getPlatformKind(), result, addressValue, asAllocatable(newValue))); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalBailoutException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalBailoutException.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.common; + +import jdk.vm.ci.code.BailoutException; +import org.graalvm.compiler.debug.CausableByCompilerAssert; + +@SuppressWarnings("serial") +public class GraalBailoutException extends BailoutException implements CausableByCompilerAssert { + + public GraalBailoutException(String format, Object... args) { + super(format, args); + } + + public GraalBailoutException(Throwable cause, String format, Object... args) { + super(cause, format, args); + } + + public GraalBailoutException(boolean permanent, String format, Object... args) { + super(permanent, format, args); + } + + @Override + public boolean isCausedByCompilerAssert() { + return false; + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java Thu May 31 13:39:26 2018 -0700 @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.core.common; -import jdk.vm.ci.code.BailoutException; - -public class PermanentBailoutException extends BailoutException { +public class PermanentBailoutException extends GraalBailoutException { private static final long serialVersionUID = -2683649650135362549L; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java Thu May 31 13:39:26 2018 -0700 @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.core.common; -import jdk.vm.ci.code.BailoutException; - -public class RetryableBailoutException extends BailoutException { +public class RetryableBailoutException extends GraalBailoutException { private static final long serialVersionUID = -7145365025679144525L; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu May 31 13:39:26 2018 -0700 @@ -1545,6 +1545,9 @@ @Override public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + if (outStamp.isEmpty()) { + return StampFactory.forInteger(inputBits).empty(); + } IntegerStamp stamp = (IntegerStamp) outStamp; long mask = CodeUtil.mask(inputBits); return StampFactory.forIntegerWithMask(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask() & mask, stamp.upMask() & mask); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,19 +27,20 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; @@ -48,9 +49,7 @@ import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.MirroredTypeException; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor7; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; @@ -58,24 +57,10 @@ import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import jdk.internal.vm.compiler.collections.EconomicMap; -import jdk.internal.vm.compiler.collections.EconomicSet; -import jdk.internal.vm.compiler.collections.Equivalence; -import org.graalvm.compiler.core.gen.NodeMatchRules; -import org.graalvm.compiler.core.match.ComplexMatchResult; -import org.graalvm.compiler.core.match.MatchRule; -import org.graalvm.compiler.core.match.MatchRules; -import org.graalvm.compiler.core.match.MatchStatement; -import org.graalvm.compiler.core.match.MatchStatementSet; -import org.graalvm.compiler.core.match.MatchableNode; -import org.graalvm.compiler.core.match.MatchableNodes; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Position; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.compiler.processor.AbstractProcessor; /** - * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is + * Processes classes annotated with {@code MatchRule}. A {@code MatchStatementSet} service is * generated for each top level class containing at least one such field. These service objects can * be retrieved as follows: * @@ -90,6 +75,13 @@ "org.graalvm.compiler.core.match.MatchableNodes"}) public class MatchProcessor extends AbstractProcessor { + private static final String VALUE_NODE_CLASS_NAME = "org.graalvm.compiler.nodes.ValueNode"; + private static final String COMPLEX_MATCH_RESULT_CLASS_NAME = "org.graalvm.compiler.core.match.ComplexMatchResult"; + private static final String MATCHABLE_NODES_CLASS_NAME = "org.graalvm.compiler.core.match.MatchableNodes"; + private static final String MATCHABLE_NODE_CLASS_NAME = "org.graalvm.compiler.core.match.MatchableNode"; + private static final String MATCH_RULE_CLASS_NAME = "org.graalvm.compiler.core.match.MatchRule"; + private static final String MATCH_RULES_CLASS_NAME = "org.graalvm.compiler.core.match.MatchRules"; + public MatchProcessor() { } @@ -98,8 +90,8 @@ return SourceVersion.latest(); } - private final Set processedMatchRule = new HashSet<>(); - private final Set processedMatchableNode = new HashSet<>(); + private final Set processedMatchRules = new HashSet<>(); + private final Set processedMatchableNodes = new HashSet<>(); private static class RuleParseError extends RuntimeException { private static final long serialVersionUID = 6456128283609257490L; @@ -170,14 +162,14 @@ if (peek("(").equals("(")) { next(); MatchDescriptor descriptor = parseType(true); - for (int n = 0; n < descriptor.nodeType.inputs.length; n++) { + for (int n = 0; n < descriptor.nodeType.inputs.size(); n++) { if (peek("(").equals("(")) { descriptor.inputs[n] = parseExpression(); } else { descriptor.inputs[n] = parseType(false); } } - for (int n = 0; n < descriptor.nodeType.inputs.length; n++) { + for (int n = 0; n < descriptor.nodeType.inputs.size(); n++) { if (descriptor.inputs[n] == null) { throw new RuleParseError("not enough inputs for " + descriptor.name); } @@ -233,7 +225,7 @@ /** * Recursively accumulate any required Position declarations. */ - void generatePositionDeclarations(EconomicSet declarations) { + void generatePositionDeclarations(Set declarations) { matchDescriptor.generatePositionDeclarations(declarations); } @@ -251,9 +243,8 @@ } /** - * Set to true to enable logging to a local file during annotation processing. There's no normal - * channel for any debug messages and debugging annotation processors requires some special - * setup. + * Set to true to enable logging during annotation processing. There's no normal channel for any + * debug messages and debugging annotation processors requires some special setup. */ private static final boolean DEBUG = false; @@ -265,14 +256,21 @@ private PrintWriter getLog() { if (log == null) { - try { - // Create the log file within the generated source directory so it's easy to find. - // /tmp isn't platform independent and java.io.tmpdir can map anywhere, particularly - // on the mac. - FileObject file = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", getClass().getSimpleName() + "log"); - log = new PrintWriter(new FileWriter(file.toUri().getPath(), true)); - } catch (IOException e) { - // Do nothing + if (processingEnv.getClass().getName().contains(".javac.")) { + // For javac, just log to System.err + log = new PrintWriter(System.err); + } else { + try { + // Create the log file within the generated source directory so it's easy to + // find. + // /tmp isn't platform independent and java.io.tmpdir can map anywhere, + // particularly + // on the mac. + FileObject file = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", getClass().getSimpleName() + "log"); + log = new PrintWriter(new FileWriter(file.toUri().getPath(), true)); + } catch (IOException e) { + // Do nothing + } } } return log; @@ -309,7 +307,7 @@ logMessage("throw for %s:\n", element); } logException(t); - errorMessage(element, "Exception throw during processing: %s %s", t, Arrays.toString(Arrays.copyOf(t.getStackTrace(), 4))); + printError(element, "Exception throw during processing: %s %s", t, Arrays.toString(Arrays.copyOf(t.getStackTrace(), 4))); } static class TypeDescriptor { @@ -321,19 +319,19 @@ final String shortName; /** - * The simple name of the {@link ValueNode} class represented by this type. + * The simple name of the {@code ValueNode} class represented by this type. */ final String nodeClass; /** - * The package of {@link ValueNode} class represented by this type. + * The package of {@code ValueNode} class represented by this type. */ final String nodePackage; /** * The matchable inputs of the node. */ - final String[] inputs; + final List inputs; /** * Should swapped variants of this match be generated. The user of the match is expected to @@ -350,7 +348,7 @@ final Set originatingElements = new HashSet<>(); - TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, String[] inputs, boolean commutative, boolean shareable) { + TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable) { this.mirror = mirror; this.shortName = shortName; this.nodeClass = nodeClass; @@ -358,26 +356,18 @@ this.inputs = inputs; this.commutative = commutative; this.shareable = shareable; - assert !commutative || inputs.length == 2; + assert !commutative || inputs.size() == 2; } } /** * The types which are know for purpose of parsing MatchRule expressions. */ - EconomicMap knownTypes = EconomicMap.create(Equivalence.DEFAULT); + Map knownTypes = new HashMap<>(); private TypeDescriptor valueType; - private TypeMirror matchRulesTypeMirror; - - private TypeMirror matchRuleTypeMirror; - - private TypeMirror matchableNodeTypeMirror; - - private TypeMirror matchableNodesTypeMirror; - - private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, String[] inputs, boolean commutative, boolean shareable, Element element) { + private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable, Element element) { TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable); descriptor.originatingElements.add(element); knownTypes.put(shortName, descriptor); @@ -388,7 +378,7 @@ if (p != null) { return p.getQualifiedName().toString(); } - throw new GraalError("can't find package for %s", type); + throw new InternalError("Can't find package for " + type); } class MatchDescriptor { @@ -400,13 +390,13 @@ this.nodeType = nodeType; this.name = name; if (forExpression) { - this.inputs = new MatchDescriptor[nodeType.inputs.length]; + this.inputs = new MatchDescriptor[nodeType.inputs.size()]; } else { this.inputs = new MatchDescriptor[0]; } } - public void generatePositionDeclarations(EconomicSet declarations) { + public void generatePositionDeclarations(Set declarations) { if (inputs.length == 0) { return; } @@ -469,10 +459,10 @@ private String formatSuffix() { if (nodeType != null) { - if (inputs.length != nodeType.inputs.length) { + if (inputs.length != nodeType.inputs.size()) { return ", true)"; } else { - if (nodeType.inputs.length > 0) { + if (nodeType.inputs.size() > 0) { return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ")"; } if (nodeType.shareable) { @@ -502,7 +492,7 @@ String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString(); Name topDeclaringClass = info.topDeclaringType.getSimpleName(); - String matchStatementClassName = topDeclaringClass + "_" + MatchStatementSet.class.getSimpleName(); + String matchStatementClassName = topDeclaringClass + "_MatchStatementSet"; Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]); Types typeUtils = typeUtils(); @@ -516,22 +506,20 @@ out.println("package " + pkg + ";"); out.println(""); out.println("import java.util.*;"); - out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;"); - out.println("import " + NodeMatchRules.class.getName() + ";"); - out.println("import " + Position.class.getName() + ";"); - out.println("import " + ServiceProvider.class.getName() + ";"); + out.println("import org.graalvm.compiler.core.match.*;"); + out.println("import org.graalvm.compiler.core.gen.NodeMatchRules;"); + out.println("import org.graalvm.compiler.graph.Position;"); for (String p : info.requiredPackages) { out.println("import " + p + ".*;"); } out.println(""); - out.println("@" + ServiceProvider.class.getSimpleName() + "(" + MatchStatementSet.class.getSimpleName() + ".class)"); - out.println("public class " + matchStatementClassName + " implements " + MatchStatementSet.class.getSimpleName() + " {"); + out.println("public class " + matchStatementClassName + " implements MatchStatementSet {"); out.println(); // Generate declarations for the wrapper class to invoke the code generation methods. - for (MethodInvokerItem invoker : info.invokers.getValues()) { + for (MethodInvokerItem invoker : info.invokers.values()) { StringBuilder args = new StringBuilder(); StringBuilder types = new StringBuilder(); int count = invoker.fields.size(); @@ -562,7 +550,7 @@ } - String desc = MatchStatement.class.getSimpleName(); + String desc = "MatchStatement"; out.println(" @Override"); out.println(" public Class forClass() {"); @@ -595,6 +583,7 @@ out.println("}"); } + this.createProviderFile(pkg + "." + matchStatementClassName, "org.graalvm.compiler.core.match.MatchStatementSet", originatingElements); } protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) { @@ -662,17 +651,17 @@ final TypeElement topDeclaringType; final List matchRules = new ArrayList<>(); - private final EconomicSet originatingElements = EconomicSet.create(Equivalence.DEFAULT); - public EconomicSet positionDeclarations = EconomicSet.create(Equivalence.DEFAULT); + private final Set originatingElements = new HashSet<>(); + public Set positionDeclarations = new HashSet<>(); /** * The mapping between elements with MatchRules and the wrapper class used invoke the code * generation after the match. */ - EconomicMap invokers = EconomicMap.create(Equivalence.DEFAULT); + Map invokers = new HashMap<>(); /** - * The set of packages which must be imported to refer the classes mention in matchRules. + * The set of packages which must be imported to refer the classes mentioned in matchRules. */ Set requiredPackages = new HashSet<>(); @@ -690,14 +679,15 @@ return topDeclaringType(enclosing); } - private AnnotationMirror findAnnotationMirror(Element element, TypeMirror typeMirror) { - for (AnnotationMirror mirror : element.getAnnotationMirrors()) { - if (typeUtils().isSameType(mirror.getAnnotationType(), typeMirror)) { - return mirror; - } - } - return null; - } + /** + * The element currently being processed. + */ + private Element currentElement; + + /** + * The current processing round. + */ + private RoundEnvironment currentRound; @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { @@ -706,45 +696,58 @@ } logMessage("Starting round %s\n", roundEnv); - matchRulesTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchRules.class.getCanonicalName()).asType(); - matchRuleTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchRule.class.getCanonicalName()).asType(); + + TypeElement matchRulesTypeElement = getTypeElement(MATCH_RULES_CLASS_NAME); + TypeElement matchRuleTypeElement = getTypeElement(MATCH_RULE_CLASS_NAME); - matchableNodeTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchableNode.class.getCanonicalName()).asType(); - matchableNodesTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchableNodes.class.getCanonicalName()).asType(); + TypeMirror matchRulesTypeMirror = matchRulesTypeElement.asType(); + TypeMirror matchRuleTypeMirror = matchRuleTypeElement.asType(); - Element currentElement = null; + TypeElement matchableNodeTypeElement = getTypeElement(MATCHABLE_NODE_CLASS_NAME); + TypeElement matchableNodesTypeElement = getTypeElement(MATCHABLE_NODES_CLASS_NAME); + + currentRound = roundEnv; try { - for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNode.class)) { + for (Element element : roundEnv.getElementsAnnotatedWith(matchableNodeTypeElement)) { + currentElement = element; logMessage("%s\n", element); - processMatchableNode(element); + processMatchableNodes(element); } - for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNodes.class)) { + for (Element element : roundEnv.getElementsAnnotatedWith(matchableNodesTypeElement)) { + currentElement = element; logMessage("%s\n", element); - processMatchableNode(element); + processMatchableNodes(element); } // Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes // table since it shouldn't be mentioned in match rules. - TypeMirror valueTypeMirror = processingEnv.getElementUtils().getTypeElement(ValueNode.class.getName()).asType(); - valueType = new TypeDescriptor(valueTypeMirror, "Value", ValueNode.class.getSimpleName(), ValueNode.class.getPackage().getName(), new String[0], false, false); + TypeMirror valueTypeMirror = getTypeElement(VALUE_NODE_CLASS_NAME).asType(); + valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false); - EconomicMap map = EconomicMap.create(Equivalence.DEFAULT); + Map map = new HashMap<>(); - for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { + for (Element element : roundEnv.getElementsAnnotatedWith(matchRuleTypeElement)) { currentElement = element; - processMatchRule(map, element, findAnnotationMirror(element, matchRuleTypeMirror)); + AnnotationMirror matchRule = getAnnotation(element, matchRuleTypeMirror); + List matchRuleAnnotations = Collections.singletonList(matchRule); + processMatchRules(map, element, matchRuleAnnotations); } - for (Element element : roundEnv.getElementsAnnotatedWith(MatchRules.class)) { + for (Element element : roundEnv.getElementsAnnotatedWith(matchRulesTypeElement)) { currentElement = element; - processMatchRule(map, element, findAnnotationMirror(element, matchRulesTypeMirror)); + AnnotationMirror matchRules = getAnnotation(element, matchRulesTypeMirror); + List matchRuleAnnotations = getAnnotationValueList(matchRules, "value", AnnotationMirror.class); + processMatchRules(map, element, matchRuleAnnotations); } currentElement = null; - for (MatchRuleDescriptor info : map.getValues()) { + for (MatchRuleDescriptor info : map.values()) { createFiles(info); } } catch (Throwable t) { reportExceptionThrow(currentElement, t); + } finally { + currentElement = null; + currentRound = null; } return true; @@ -753,27 +756,27 @@ /** * Build up the type table to be used during parsing of the MatchRule. */ - private void processMatchableNode(Element element) { - if (!processedMatchableNode.contains(element)) { + private void processMatchableNodes(Element element) { + if (!processedMatchableNodes.contains(element)) { try { - processedMatchableNode.add(element); + processedMatchableNodes.add(element); - AnnotationMirror mirror = findAnnotationMirror(element, matchableNodesTypeMirror); - if (mirror == null) { - mirror = findAnnotationMirror(element, matchableNodeTypeMirror); + List matchableNodeAnnotations; + AnnotationMirror mirror = getAnnotation(element, getType(MATCHABLE_NODES_CLASS_NAME)); + if (mirror != null) { + matchableNodeAnnotations = getAnnotationValueList(mirror, "value", AnnotationMirror.class); + } else { + mirror = getAnnotation(element, getType(MATCHABLE_NODES_CLASS_NAME)); + if (mirror != null) { + matchableNodeAnnotations = Collections.singletonList(mirror); + } else { + return; + } } - if (mirror == null) { - return; - } + TypeElement topDeclaringType = topDeclaringType(element); - List mirrors = null; - if (typeUtils().isSameType(mirror.getAnnotationType(), matchableNodesTypeMirror)) { - // Unpack the mirrors for a repeatable annotation - mirrors = getAnnotationValueList(AnnotationMirror.class, mirror, "value"); - } - int i = 0; - for (MatchableNode matchableNode : element.getAnnotationsByType(MatchableNode.class)) { - processMatchableNode(element, topDeclaringType, matchableNode, mirrors != null ? mirrors.get(i++) : mirror); + for (AnnotationMirror matchableNode : matchableNodeAnnotations) { + processMatchableNode(element, topDeclaringType, matchableNode); } } catch (Throwable t) { reportExceptionThrow(element, t); @@ -781,27 +784,22 @@ } } - private void processMatchableNode(Element element, TypeElement topDeclaringType, MatchableNode matchable, AnnotationMirror mirror) throws GraalError { + private void processMatchableNode(Element element, TypeElement topDeclaringType, AnnotationMirror matchable) { logMessage("processMatchableNode %s %s %s\n", topDeclaringType, element, matchable); String nodeClass; String nodePackage; - TypeMirror nodeClassMirror = null; - try { - matchable.nodeClass(); - } catch (MirroredTypeException e) { - nodeClassMirror = e.getTypeMirror(); + TypeMirror nodeClassMirror = getAnnotationValue(matchable, "nodeClass", TypeMirror.class); + if (nodeClassMirror == null) { + throw new InternalError("Can't get mirror for node class " + element); } - if (nodeClassMirror == null) { - throw new GraalError("Can't get mirror for node class %s", element); - } - if (nodeClassMirror.toString().equals(MatchableNode.class.getName())) { + if (nodeClassMirror.toString().equals(MATCHABLE_NODE_CLASS_NAME)) { nodeClass = topDeclaringType.getQualifiedName().toString(); } else { nodeClass = nodeClassMirror.toString(); } TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(nodeClass); if (typeElement == null) { - errorMessage(element, mirror, "Class \"%s\" cannot be resolved to a type", nodeClass); + printError(element, matchable, "Class \"%s\" cannot be resolved to a type", nodeClass); return; } nodePackage = findPackage(typeElement); @@ -812,7 +810,8 @@ Types typeUtils = processingEnv.getTypeUtils(); TypeElement nodeClassElement = (TypeElement) typeUtils.asElement(nodeClassMirror); - for (String input : matchable.inputs()) { + List inputs = getAnnotationValueList(matchable, "inputs", String.class); + for (String input : inputs) { boolean ok = false; TypeElement current = nodeClassElement; while (!ok && current != null) { @@ -826,17 +825,19 @@ current = (TypeElement) typeUtils.asElement(theSuper); } if (!ok) { - errorMessage(element, mirror, "Input named \"%s\" doesn't exist in %s", input, nodeClassElement.getSimpleName()); + printError(element, matchable, "Input named \"%s\" doesn't exist in %s", input, nodeClassElement.getSimpleName()); } } - declareType(nodeClassMirror, shortName, nodeClass, nodePackage, matchable.inputs(), matchable.commutative(), matchable.shareable(), element); + boolean commutative = getAnnotationValue(matchable, "commutative", Boolean.class); + boolean shareable = getAnnotationValue(matchable, "shareable", Boolean.class); + declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, element); } - private void processMatchRule(EconomicMap map, Element element, AnnotationMirror mirror) { - if (!processedMatchRule.contains(element)) { + private void processMatchRules(Map map, Element element, List matchRules) { + if (!processedMatchRules.contains(element)) { try { - processedMatchRule.add(element); + processedMatchRules.add(element); // The annotation element type should ensure this is true. assert element instanceof ExecutableElement; @@ -849,14 +850,8 @@ info = new MatchRuleDescriptor(topDeclaringType); map.put(topDeclaringType, info); } - List mirrors = null; - if (typeUtils().isSameType(mirror.getAnnotationType(), matchRulesTypeMirror)) { - // Unpack the mirrors for a repeatable annotation - mirrors = getAnnotationValueList(AnnotationMirror.class, mirror, "value"); - } - int i = 0; - for (MatchRule matchRule : element.getAnnotationsByType(MatchRule.class)) { - processMethodMatchRule((ExecutableElement) element, info, matchRule, mirrors != null ? mirrors.get(i++) : mirror); + for (AnnotationMirror matchRule : matchRules) { + processMatchRule((ExecutableElement) element, info, matchRule); } } catch (Throwable t) { reportExceptionThrow(element, t); @@ -871,16 +866,16 @@ * @param element */ private void findMatchableNodes(Element element) { - processMatchableNode(element); + processMatchableNodes(element); Element enclosing = element.getEnclosingElement(); while (enclosing != null) { if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { TypeElement current = (TypeElement) enclosing; while (current != null) { - processMatchableNode(current); + processMatchableNodes(current); for (TypeMirror intf : current.getInterfaces()) { Element interfaceElement = typeUtils().asElement(intf); - processMatchableNode(interfaceElement); + processMatchableNodes(interfaceElement); // Recurse findMatchableNodes(interfaceElement); } @@ -896,34 +891,34 @@ return processingEnv.getTypeUtils(); } - private void processMethodMatchRule(ExecutableElement method, MatchRuleDescriptor info, MatchRule matchRule, AnnotationMirror mirror) { - logMessage("processMethodMatchRule %s %s\n", method, mirror); + private void processMatchRule(ExecutableElement method, MatchRuleDescriptor info, AnnotationMirror matchRule) { + logMessage("processMatchRule %s\n", method); Types typeUtils = typeUtils(); if (!method.getModifiers().contains(Modifier.PUBLIC)) { - errorMessage(method, "MatchRule method %s must be public", method.getSimpleName()); + printError(method, "MatchRule method %s must be public", method.getSimpleName()); return; } if (method.getModifiers().contains(Modifier.STATIC)) { - errorMessage(method, "MatchRule method %s must be non-static", method.getSimpleName()); + printError(method, "MatchRule method %s must be non-static", method.getSimpleName()); return; } try { TypeMirror returnType = method.getReturnType(); - if (!typeUtils.isSameType(returnType, processingEnv.getElementUtils().getTypeElement(ComplexMatchResult.class.getName()).asType())) { - errorMessage(method, "MatchRule method return type must be %s", ComplexMatchResult.class.getName()); + if (!typeUtils.isSameType(returnType, processingEnv.getElementUtils().getTypeElement(COMPLEX_MATCH_RESULT_CLASS_NAME).asType())) { + printError(method, "MatchRule method return type must be %s", COMPLEX_MATCH_RESULT_CLASS_NAME); return; } - String rule = matchRule.value(); + String rule = getAnnotationValue(matchRule, "value", String.class); RuleParser parser = new RuleParser(rule); ArrayList expectedTypes = parser.capturedTypes(); ArrayList expectedNames = parser.capturedNames(); List actualParameters = method.getParameters(); if (expectedTypes.size() + 1 < actualParameters.size()) { - errorMessage(method, "Too many arguments for match method %s != %s", expectedTypes.size() + 1, actualParameters.size()); + printError(method, "Too many arguments for match method %s != %s", expectedTypes.size() + 1, actualParameters.size()); return; } @@ -934,12 +929,12 @@ String name = parameter.getSimpleName().toString(); int nameIndex = expectedNames.indexOf(name); if (nameIndex == -1) { - errorMessage(method, "Argument \"%s\" isn't captured in the match rule", name); + printError(method, "Argument \"%s\" isn't captured in the match rule", name); return; } TypeMirror type = parameter.asType(); if (!typeUtils.isAssignable(expectedTypes.get(nameIndex).mirror, type)) { - errorMessage(method, "Captured value \"%s\" of type %s is not assignable to argument of type %s", name, expectedTypes.get(nameIndex).mirror, type); + printError(method, "Captured value \"%s\" of type %s is not assignable to argument of type %s", name, expectedTypes.get(nameIndex).mirror, type); return; } } @@ -952,7 +947,7 @@ } else if (invoker.method != method) { // This could be supported but it's easier if they are unique since the names // are used in log output and snippet counters. - errorMessage(method, "Use unique method names for match methods: %s.%s != %s.%s", method.getReceiverType(), method.getSimpleName(), invoker.method.getReceiverType(), + printError(method, "Use unique method names for match methods: %s.%s != %s.%s", method.getReceiverType(), method.getSimpleName(), invoker.method.getReceiverType(), invoker.method.getSimpleName()); return; } @@ -960,12 +955,12 @@ Element enclosing = method.getEnclosingElement(); String declaringClass = ""; String separator = ""; - EconomicSet originatingElementsList = info.originatingElements; + Set originatingElementsList = info.originatingElements; originatingElementsList.add(method); while (enclosing != null) { if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { if (enclosing.getModifiers().contains(Modifier.PRIVATE)) { - errorMessage(method, "MatchRule cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); + printError(method, "MatchRule cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); return; } originatingElementsList.add(enclosing); @@ -988,144 +983,26 @@ info.matchRules.add(new MatchRuleItem(match, invoker)); } } catch (RuleParseError e) { - errorMessage(method, mirror, e.getMessage()); + printError(method, matchRule, e.getMessage()); } } - private void errorMessage(Element element, String format, Object... args) { - processingEnv.getMessager().printMessage(Kind.ERROR, String.format(format, args), element); - } - - private void errorMessage(Element element, AnnotationMirror mirror, String format, Object... args) { - processingEnv.getMessager().printMessage(Kind.ERROR, String.format(format, args), element, mirror); - } - - // TODO borrowed from com.oracle.truffle.dsl.processor.Utils - @SuppressWarnings("unchecked") - private static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { - List values = getAnnotationValue(List.class, mirror, name); - List result = new ArrayList<>(); - - if (values != null) { - for (AnnotationValue value : values) { - T annotationValue = resolveAnnotationValue(expectedListType, value); - if (annotationValue != null) { - result.add(annotationValue); - } - } + private Element elementForMessage(Element e) { + if (currentRound != null && !currentRound.getRootElements().contains(e) && currentElement != null) { + return currentElement; } - return result; - } - - private static T getAnnotationValue(Class expectedType, AnnotationMirror mirror, String name) { - return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); - } - - @SuppressWarnings({"unchecked"}) - private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { - if (value == null) { - return null; - } - - Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); - if (unboxedValue != null) { - if (expectedType == TypeMirror.class && unboxedValue instanceof String) { - return null; - } - if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { - throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); - } - } - return (T) unboxedValue; - } - - private static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { - ExecutableElement valueMethod = null; - for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { - if (method.getSimpleName().toString().equals(name)) { - valueMethod = method; - break; - } - } - - if (valueMethod == null) { - return null; - } - - AnnotationValue value = mirror.getElementValues().get(valueMethod); - if (value == null) { - value = valueMethod.getDefaultValue(); - } - - return value; + return e; } - private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7 { - - @Override - public Object visitBoolean(boolean b, Void p) { - return Boolean.valueOf(b); - } - - @Override - public Object visitByte(byte b, Void p) { - return Byte.valueOf(b); - } - - @Override - public Object visitChar(char c, Void p) { - return c; - } - - @Override - public Object visitDouble(double d, Void p) { - return d; - } - - @Override - public Object visitFloat(float f, Void p) { - return f; - } - - @Override - public Object visitInt(int i, Void p) { - return i; - } + private void printError(Element annotatedElement, String format, Object... args) { + Element e = elementForMessage(annotatedElement); + String prefix = e == annotatedElement ? "" : annotatedElement + ": "; + processingEnv.getMessager().printMessage(Kind.ERROR, prefix + String.format(format, args), e); + } - @Override - public Object visitLong(long i, Void p) { - return i; - } - - @Override - public Object visitShort(short s, Void p) { - return s; - } - - @Override - public Object visitString(String s, Void p) { - return s; - } - - @Override - public Object visitType(TypeMirror t, Void p) { - return t; - } - - @Override - public Object visitEnumConstant(VariableElement c, Void p) { - return c; - } - - @Override - public Object visitAnnotation(AnnotationMirror a, Void p) { - return a; - } - - @Override - public Object visitArray(List vals, Void p) { - return vals; - } - + private void printError(Element annotatedElement, AnnotationMirror annotation, String format, Object... args) { + Element e = elementForMessage(annotatedElement); + String prefix = e == annotatedElement ? "" : annotation + " on " + annotatedElement + ": "; + processingEnv.getMessager().printMessage(Kind.ERROR, prefix + String.format(format, args), e, annotation); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Thu May 31 13:39:26 2018 -0700 @@ -169,7 +169,7 @@ SPARCAddressValue address = (SPARCAddressValue) operand(cas.getAddress()); Condition condition = successIsTrue ? Condition.EQ : Condition.NE; - Value result = getLIRGeneratorTool().emitValueCompareAndSwap(address, expectedValue, newValue); + Value result = getLIRGeneratorTool().emitValueCompareAndSwap(kind, address, expectedValue, newValue); getLIRGeneratorTool().emitCompareBranch(kind.getPlatformKind(), result, expectedValue, condition, false, trueLabel, falseLabel, trueLabelProbability); return null; }; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ArrayLengthProviderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ArrayLengthProviderTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +public class ArrayLengthProviderTest extends GraalCompilerTest { + + public static Object test0Snippet(ArrayList list, boolean a) { + while (true) { + Object[] array = toArray(list); + if (array.length < 1) { + return null; + } + if (array[0] instanceof String || a) { + /* + * This code is outside of the loop. Accessing the array reqires a ValueProxyNode. + * When the simplification of the ArrayLengthNode replaces the length access with + * the ArrayList.size used to create the array, then the value needs to have a + * ValueProxyNode too. In addition, the two parts of the if-condition actually lead + * to two separate loop exits, with two separate proxy nodes. A ValuePhiNode is + * present originally for the array, and the array length simplification needs to + * create a new ValuePhiNode for the two newly introduced ValueProxyNode. + */ + if (array.length < 1) { + return null; + } + return array[0]; + } + } + } + + public static Object test1Snippet(ArrayList list, boolean a, boolean b) { + while (true) { + Object[] array = toArray(list); + if (a || b) { + if (array.length < 1) { + return null; + } + return array[0]; + } + } + } + + public static Object[] toArray(List list) { + return new Object[list.size()]; + } + + @Test + public void test0() { + test("test0Snippet", new ArrayList<>(Arrays.asList("a", "b")), true); + } + + @Test + public void test1() { + test("test1Snippet", new ArrayList<>(Arrays.asList("a", "b")), true, true); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CanonicalizedConversionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CanonicalizedConversionTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.calc.AddNode; +import org.graalvm.compiler.nodes.calc.FloatEqualsNode; +import org.graalvm.compiler.nodes.calc.ReinterpretNode; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests that substitutions for {@link Double#doubleToLongBits(double)} and + * {@link Float#floatToIntBits(float)} produce graphs such that multiple calls to these methods with + * the same input are canonicalized. + */ +public class CanonicalizedConversionTest extends GraalCompilerTest { + + @Override + protected boolean checkLowTierGraph(StructuredGraph graph) { + int reinterpretCount = 0; + int floatEqualsCount = 0; + int addCount = 0; + for (Node node : graph.getNodes()) { + if (node instanceof ReinterpretNode) { + reinterpretCount++; + } else if (node instanceof FloatEqualsNode) { + floatEqualsCount++; + } else if (node instanceof IfNode) { + Assert.fail("Unexpected node: " + node); + } else if (node instanceof AddNode) { + addCount++; + } + } + Assert.assertEquals(1, reinterpretCount); + Assert.assertEquals(1, floatEqualsCount); + Assert.assertEquals(2, addCount); + return true; + } + + @Test + public void test4() { + test("snippet4", 567.890F); + test("snippet4", -567.890F); + test("snippet4", Float.NaN); + } + + public static int snippet4(float value) { + return Float.floatToIntBits(value) + Float.floatToIntBits(value) + Float.floatToIntBits(value); + } + + @Test + public void test5() { + test("snippet5", 567.890D); + test("snippet5", -567.890D); + test("snippet5", Double.NaN); + } + + public static long snippet5(double value) { + return Double.doubleToLongBits(value) + Double.doubleToLongBits(value) + Double.doubleToLongBits(value); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; +import org.junit.Assert; +import org.junit.Test; + +/** + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. + */ +public class ConditionalEliminationTest15 extends ConditionalEliminationTestBase { + + private void checkNodeCount(String methodName, Class nodeClass, int count) { + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); + + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + PhaseContext context = new PhaseContext(getProviders()); + + new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + canonicalizer.apply(graph, context); + + // Merge arr.length reads. + new EarlyReadEliminationPhase(canonicalizer).apply(graph, context); + new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); + + getDebugContext().dump(DebugContext.BASIC_LEVEL, graph, "After ConditionalEliminationPhase"); + + Assert.assertEquals(count, graph.getNodes().filter(nodeClass).count()); + } + + public static int testRedundantIntegerLessThanNode(int index, int[] arr) { + while (arr[index] != 42) { + if (index >= 0) { // redundant + return 1; + } + } + return 2; + } + + public static int testRedundantIntegerLessThanNode2(int index, int[] arr) { + while (arr[index] != 42) { + if (index < arr.length) { // redundant + return 1; + } + } + return 2; + } + + @Test + public void testRedundantSignedLessThanNode() { + checkNodeCount("testRedundantIntegerLessThanNode", IntegerLessThanNode.class, 0); + checkNodeCount("testRedundantIntegerLessThanNode2", IntegerLessThanNode.class, 0); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java Thu May 31 13:39:26 2018 -0700 @@ -22,15 +22,18 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; import org.junit.Test; /** @@ -60,6 +63,15 @@ final Entry next; } + static class A { + } + + static class B extends A { + } + + static class C extends A { + } + public static Entry search(Entry start, String name, Entry alternative) { Entry current = start; do { @@ -129,4 +141,81 @@ assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count()); } + private void checkInstanceOfCount(String methodName, int count) { + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); + + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + PhaseContext context = new PhaseContext(getProviders()); + + canonicalizer.apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); + getDebugContext().dump(DebugContext.BASIC_LEVEL, graph, "After ConditionalEliminationPhase"); + canonicalizer.apply(graph, context); + + Assert.assertEquals(count, graph.getNodes().filter(InstanceOfNode.class).count()); + } + + public static A testRedundantInstanceOfClass(Object value) { + if (value != null && value.getClass() == A.class) { + return (A) value; + } + return null; + } + + public static Object testRedundantInstanceOfArray(Object value) { + if (value != null && value.getClass() == Object[].class) { + return ((Object[]) value)[0]; + } + return null; + } + + public static boolean testRedundantInstanceOfPrecise(Object value) { + if (value != null && value.getClass() == A.class) { + return value instanceof A; + } + return false; + } + + public static boolean testRedundantInstanceOfImplicitNonNull(Object value) { + if (value.getClass() == A.class) { + return value instanceof A; + } + return false; + } + + @Test + public void testRedundantInstanceOf() { + checkInstanceOfCount("testRedundantInstanceOfClass", 1); + checkInstanceOfCount("testRedundantInstanceOfArray", 1); + checkInstanceOfCount("testRedundantInstanceOfPrecise", 1); + checkInstanceOfCount("testRedundantInstanceOfImplicitNonNull", 1); + } + + public static boolean testNonRedundantInstanceOfClass(Object value) { + if (value instanceof A) { + return (value != null && value.getClass() == A.class); + } + return false; + } + + public static boolean testNonRedundantInstanceOfArray(Object value) { + if (value instanceof Object[]) { + return (value != null && value.getClass() == Object[].class); + } + return false; + } + + public static boolean testNonRedundantInstanceOfImplicitNonNull(Object value) { + if (value instanceof Object[]) { + return value.getClass() == Object[].class; + } + return false; + } + + @Test + public void testNonRedundantInstanceOf() { + checkInstanceOfCount("testNonRedundantInstanceOfClass", 2); + checkInstanceOfCount("testNonRedundantInstanceOfArray", 2); + checkInstanceOfCount("testNonRedundantInstanceOfImplicitNonNull", 2); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu May 31 13:39:26 2018 -0700 @@ -1054,7 +1054,7 @@ try (DebugContext.Scope s = debug.scope("Compile", graphToCompile)) { assert options != null; Request request = new Request<>(graphToCompile, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, - graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default); + graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default, true); return GraalCompiler.compile(request); } catch (Throwable e) { throw debug.handle(e); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java Thu May 31 13:39:26 2018 -0700 @@ -68,7 +68,7 @@ final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); final StructuredGraph graph = parseEager(method, AllowAssumptions.YES); final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default); + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default, true); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -90,7 +90,7 @@ assertTrue(graphLineSPs > 0); PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)); final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), - createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default); + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default, true); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java Thu May 31 13:39:26 2018 -0700 @@ -127,7 +127,7 @@ CompilationResultBuilderFactory factory = CompilationResultBuilderFactory.Default; /* Invoke the whole Graal compilation pipeline. */ - GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory); + GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory, true); /* * Install the compilation result into the VM, i.e., copy the byte[] array that contains diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Thu May 31 13:39:26 2018 -0700 @@ -106,6 +106,7 @@ public final LIRSuites lirSuites; public final T compilationResult; public final CompilationResultBuilderFactory factory; + public final boolean verifySourcePositions; /** * @param graph the graph to be compiled @@ -122,7 +123,8 @@ * @param factory */ public Request(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, PhaseSuite graphBuilderSuite, - OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory) { + OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory, + boolean verifySourcePositions) { this.graph = graph; this.installedCodeOwner = installedCodeOwner; this.providers = providers; @@ -134,6 +136,7 @@ this.lirSuites = lirSuites; this.compilationResult = compilationResult; this.factory = factory; + this.verifySourcePositions = verifySourcePositions; } /** @@ -156,8 +159,9 @@ */ public static T compileGraph(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, - CompilationResultBuilderFactory factory) { - return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory)); + CompilationResultBuilderFactory factory, boolean verifySourcePositions) { + return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory, + verifySourcePositions)); } /** @@ -173,6 +177,9 @@ try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites); + if (r.verifySourcePositions) { + assert r.graph.verifySourcePositions(true); + } } catch (Throwable e) { throw debug.handle(e); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.gen; -import jdk.vm.ci.meta.Value; - import org.graalvm.compiler.core.match.MatchableNode; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.lir.LIRFrameState; @@ -62,6 +60,8 @@ import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; +import jdk.vm.ci.meta.Value; + @MatchableNode(nodeClass = ConstantNode.class, shareable = true) @MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"value"}) @MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"address"}) diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Thu May 31 13:39:26 2018 -0700 @@ -167,6 +167,32 @@ } @Test + public void testContextScope() { + OptionValues options = new OptionValues(EconomicMap.create()); + options = new OptionValues(options, DebugOptions.Log, ":5"); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options)) { + try (DebugContext.Scope s0 = debug.scope("TestLogging")) { + try (DebugContext.Scope s1 = debug.withContext("A")) { + for (Object o : debug.context()) { + Assert.assertEquals(o, "A"); + } + } catch (Throwable t) { + throw debug.handle(t); + } + try (DebugContext.Scope s1 = debug.withContext("B")) { + for (Object o : debug.context()) { + Assert.assertEquals(o, "B"); + } + } catch (Throwable t) { + throw debug.handle(t); + } + } + } + + } + + @Test public void testEnabledSandbox() { EconomicMap, Object> map = EconomicMap.create(); // Configure with an option that enables scopes diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CausableByCompilerAssert.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CausableByCompilerAssert.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +public interface CausableByCompilerAssert { + boolean isCausedByCompilerAssert(); +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java Thu May 31 13:39:26 2018 -0700 @@ -239,8 +239,11 @@ @Override public RuntimeException interceptException(DebugContext debug, Throwable e) { - if (e instanceof BailoutException && !DebugOptions.InterceptBailout.getValue(options)) { - return null; + if (e instanceof BailoutException) { + final boolean causedByCompilerAssert = e instanceof CausableByCompilerAssert && ((CausableByCompilerAssert) e).isCausedByCompilerAssert(); + if (!DebugOptions.InterceptBailout.getValue(options) && !causedByCompilerAssert) { + return null; + } } OptionValues interceptOptions = new OptionValues(options, diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Thu May 31 13:39:26 2018 -0700 @@ -96,7 +96,7 @@ */ boolean metricsEnabled; - DebugConfig currentConfig; + DebugConfigImpl currentConfig; ScopeImpl currentScope; CloseableCounter currentTimer; CloseableCounter currentMemUseTracker; @@ -739,6 +739,19 @@ } /** + * Create an unnamed scope that appends some context to the current scope. + * + * @param context an object to be appended to the {@linkplain #context() current} debug context + */ + public DebugContext.Scope withContext(Object context) throws Throwable { + if (currentScope != null) { + return enterScope("", null, context); + } else { + return null; + } + } + + /** * Creates and enters a new debug scope which will be disjoint from the current debug scope. *

* It is recommended to use the try-with-resource statement for managing entering and leaving @@ -787,7 +800,7 @@ class DisabledScope implements DebugContext.Scope { final boolean savedMetricsEnabled; final ScopeImpl savedScope; - final DebugConfig savedConfig; + final DebugConfigImpl savedConfig; DisabledScope() { this.savedMetricsEnabled = metricsEnabled; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueMap.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueMap.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +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. - */ -package org.graalvm.compiler.debug; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A node in a tree of values. - */ -public class DebugValueMap { - - /** - * The top level maps for all threads. - */ - private static final List topLevelMaps = new ArrayList<>(); - - private long[] values; - private List children; - private String name; - - public DebugValueMap(String name) { - this.name = name; - } - - public void setCurrentValue(int index, long l) { - ensureSize(index); - values[index] = l; - } - - public long getCurrentValue(int index) { - ensureSize(index); - return values[index]; - } - - public void clearChildren() { - if (children != null) { - children.clear(); - } - } - - public void reset() { - if (values != null) { - Arrays.fill(values, 0L); - } - if (children != null) { - for (DebugValueMap child : children) { - child.reset(); - } - } - } - - private void ensureSize(int index) { - if (values == null) { - values = new long[index + 1]; - } - if (values.length <= index) { - values = Arrays.copyOf(values, index + 1); - } - } - - private int capacity() { - return (values == null) ? 0 : values.length; - } - - public void addChild(DebugValueMap map) { - if (children == null) { - children = new ArrayList<>(4); - } - children.add(map); - } - - public List getChildren() { - if (children == null) { - return Collections.emptyList(); - } else { - return Collections.unmodifiableList(children); - } - } - - public boolean hasChildren() { - return children != null && !children.isEmpty(); - } - - public String getName() { - return this.name; - } - - @Override - public String toString() { - return "DebugValueMap<" + getName() + ">"; - } - - public static synchronized void registerTopLevel(DebugValueMap map) { - topLevelMaps.add(map); - } - - public static synchronized List getTopLevelMaps() { - return topLevelMaps; - } - - /** - * The top level map for the current thread. - */ - private static final ThreadLocal topLevelMap = new ThreadLocal<>(); - - static DebugValueMap getTopLevelMap() { - DebugValueMap map = topLevelMap.get(); - if (map == null) { - map = new DebugValueMap(Thread.currentThread().getName()); - topLevelMap.set(map); - registerTopLevel(map); - } - return map; - } - - public void normalize() { - if (hasChildren()) { - Map occurred = new HashMap<>(); - for (DebugValueMap map : children) { - String mapName = map.getName(); - if (!occurred.containsKey(mapName)) { - occurred.put(mapName, map); - map.normalize(); - } else { - occurred.get(mapName).mergeWith(map); - occurred.get(mapName).normalize(); - } - } - - if (occurred.values().size() < children.size()) { - // At least one duplicate was found. - children.clear(); - for (DebugValueMap map : occurred.values()) { - addChild(map); - map.normalize(); - } - } - } - } - - private void mergeWith(DebugValueMap map) { - if (map.hasChildren()) { - if (hasChildren()) { - children.addAll(map.children); - } else { - children = map.children; - } - map.children = null; - } - - int size = Math.max(this.capacity(), map.capacity()); - ensureSize(size); - for (int i = 0; i < size; ++i) { - long curValue = getCurrentValue(i); - long otherValue = map.getCurrentValue(i); - setCurrentValue(i, curValue + otherValue); - } - } - - public void group() { - if (this.hasChildren()) { - List oldChildren = new ArrayList<>(this.children); - this.children.clear(); - for (DebugValueMap map : oldChildren) { - mergeWith(map); - } - } - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Thu May 31 13:39:26 2018 -0700 @@ -72,9 +72,10 @@ /** * A maximum file name length supported by most file systems. There is no platform independent - * way to get this in Java. + * way to get this in Java. Normally it is 255. But for AUFS it is 242. Refer AUFS_MAX_NAMELEN + * in http://aufs.sourceforge.net/aufs3/man.html. */ - private static final int MAX_FILE_NAME_LENGTH = 255; + private static final int MAX_FILE_NAME_LENGTH = 242; private static final String ELLIPSIS = "..."; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java Thu May 31 13:39:26 2018 -0700 @@ -38,31 +38,35 @@ final String indent; final IndentImpl parentIndent; + boolean isEmitted() { + return emitted; + } + + private boolean emitted; + IndentImpl(IndentImpl parentIndent) { this.parentIndent = parentIndent; this.indent = (parentIndent == null ? "" : parentIndent.indent + INDENTATION_INCREMENT); } - private boolean logScopeName() { - return logScopeName; - } - private void printScopeName(StringBuilder str, boolean isCurrent) { - if (logScopeName) { - boolean parentPrinted = false; + if (!emitted) { + boolean mustPrint = true; if (parentIndent != null) { - parentPrinted = parentIndent.logScopeName(); - parentIndent.printScopeName(str, false); + if (!parentIndent.isEmitted()) { + parentIndent.printScopeName(str, false); + mustPrint = false; + } } /* - * Always print the current scope, scopes with context and the any scope whose - * parent didn't print. This ensure the first new scope always shows up. + * Always print the current scope, scopes with context and any scope whose parent + * didn't print. This ensure the first new scope always shows up. */ - if (isCurrent || printContext(null) != 0 || !parentPrinted) { + if (isCurrent || printContext(null) != 0 || mustPrint) { str.append(indent).append("[thread:").append(Thread.currentThread().getId()).append("] scope: ").append(getQualifiedName()).append(System.lineSeparator()); } printContext(str); - logScopeName = false; + emitted = true; } } @@ -116,7 +120,12 @@ private final ScopeImpl parent; private final boolean sandbox; private IndentImpl lastUsedIndent; - private boolean logScopeName; + + private boolean isEmptyScope() { + return emptyScope; + } + + private final boolean emptyScope; private final Object[] context; @@ -136,23 +145,24 @@ private PrintStream output; private boolean interceptDisabled; - static final Object[] EMPTY_CONTEXT = new Object[0]; - ScopeImpl(DebugContext owner, Thread thread) { this(owner, thread.getName(), null, false); } - ScopeImpl(DebugContext owner, String unqualifiedName, ScopeImpl parent, boolean sandbox, Object... context) { + private ScopeImpl(DebugContext owner, String unqualifiedName, ScopeImpl parent, boolean sandbox, Object... context) { this.owner = owner; this.parent = parent; this.sandbox = sandbox; this.context = context; this.unqualifiedName = unqualifiedName; if (parent != null) { - logScopeName = !unqualifiedName.equals(""); + emptyScope = unqualifiedName.equals(""); this.interceptDisabled = parent.interceptDisabled; } else { - logScopeName = true; + if (unqualifiedName.isEmpty()) { + throw new IllegalArgumentException("root scope name must be non-empty"); + } + emptyScope = false; } this.output = TTY.out; @@ -169,29 +179,29 @@ return parent == null; } - public boolean isDumpEnabled(int dumpLevel) { + boolean isDumpEnabled(int dumpLevel) { assert dumpLevel >= 0; return currentDumpLevel >= dumpLevel; } - public boolean isVerifyEnabled() { + boolean isVerifyEnabled() { return verifyEnabled; } - public boolean isLogEnabled(int logLevel) { + boolean isLogEnabled(int logLevel) { assert logLevel > 0; return currentLogLevel >= logLevel; } - public boolean isCountEnabled() { + boolean isCountEnabled() { return countEnabled; } - public boolean isTimeEnabled() { + boolean isTimeEnabled() { return timeEnabled; } - public boolean isMemUseTrackingEnabled() { + boolean isMemUseTrackingEnabled() { return memUseTrackingEnabled; } @@ -307,7 +317,7 @@ throw silenceException(RuntimeException.class, e); } - void updateFlags(DebugConfig config) { + void updateFlags(DebugConfigImpl config) { if (config == null) { countEnabled = false; memUseTrackingEnabled = false; @@ -317,6 +327,14 @@ // Be pragmatic: provide a default log stream to prevent a crash if the stream is not // set while logging output = TTY.out; + } else if (isEmptyScope()) { + countEnabled = parent.countEnabled; + memUseTrackingEnabled = parent.memUseTrackingEnabled; + timeEnabled = parent.timeEnabled; + verifyEnabled = parent.verifyEnabled; + output = parent.output; + currentDumpLevel = parent.currentDumpLevel; + currentLogLevel = parent.currentLogLevel; } else { countEnabled = config.isCountEnabled(this); memUseTrackingEnabled = config.isMemUseTrackingEnabled(this); @@ -404,18 +422,21 @@ if (parent == null) { qualifiedName = unqualifiedName; } else { - qualifiedName = parent.getQualifiedName() + SCOPE_SEP + unqualifiedName; + qualifiedName = parent.getQualifiedName(); + if (!isEmptyScope()) { + qualifiedName += SCOPE_SEP + unqualifiedName; + } } } return qualifiedName; } - public Indent pushIndentLogger() { + Indent pushIndentLogger() { lastUsedIndent = getLastUsedIndent().indent(); return lastUsedIndent; } - public IndentImpl getLastUsedIndent() { + private IndentImpl getLastUsedIndent() { if (lastUsedIndent == null) { if (parent != null) { lastUsedIndent = new IndentImpl(parent.getLastUsedIndent()); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu May 31 13:39:26 2018 -0700 @@ -1199,7 +1199,7 @@ return true; } - public boolean verifySourcePositions() { + public boolean verifySourcePositions(boolean performConsistencyCheck) { if (trackNodeSourcePosition()) { ResolvedJavaMethod root = null; for (Node node : getNodes()) { @@ -1211,6 +1211,11 @@ assert pos.verifyRootMethod(root) : node; } } + + // More strict node-type-specific check + if (performConsistencyCheck) { + node.verifySourcePosition(); + } } } return true; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu May 31 13:39:26 2018 -0700 @@ -263,7 +263,7 @@ static class NodeCreationStackTrace extends NodeStackTrace { } - static class NodeInsertionStackTrace extends NodeStackTrace { + public static class NodeInsertionStackTrace extends NodeStackTrace { } public Node(NodeClass c) { @@ -1063,6 +1063,10 @@ return true; } + public boolean verifySourcePosition() { + return true; + } + /** * Perform expensive verification of inputs, usages, predecessors and successors. * diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Thu May 31 13:39:26 2018 -0700 @@ -51,6 +51,7 @@ import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Edges.Type; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; @@ -125,11 +126,33 @@ } public static NodeClass get(Class clazz) { - NodeClass result = getUnchecked(clazz); - if (result == null && clazz != NODE_CLASS) { - throw GraalError.shouldNotReachHere("TYPE field not initialized for class " + clazz.getTypeName()); + int numTries = 0; + while (true) { + boolean shouldBeInitializedBefore = UnsafeAccess.UNSAFE.shouldBeInitialized(clazz); + + NodeClass result = getUnchecked(clazz); + if (result != null || clazz == NODE_CLASS) { + return result; + } + + /* + * GR-9537: We observed a transient problem with TYPE fields being null. Retry a couple + * of times and print something to the log so that we can gather more diagnostic + * information without failing gates. + */ + numTries++; + boolean shouldBeInitializedAfter = UnsafeAccess.UNSAFE.shouldBeInitialized(clazz); + String msg = "GR-9537 Reflective field access of TYPE field returned null. This is probably a bug in HotSpot class initialization. " + + " clazz: " + clazz.getTypeName() + ", numTries: " + numTries + + ", shouldBeInitializedBefore: " + shouldBeInitializedBefore + ", shouldBeInitializedAfter: " + shouldBeInitializedAfter; + if (numTries <= 100) { + TTY.println(msg); + UnsafeAccess.UNSAFE.ensureClassInitialized(clazz); + } else { + throw GraalError.shouldNotReachHere(msg); + } + return result; } - return result; } private static final Class NODE_CLASS = Node.class; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Thu May 31 13:39:26 2018 -0700 @@ -29,6 +29,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import jdk.internal.vm.compiler.collections.EconomicSet; @@ -41,6 +42,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -48,6 +50,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; +import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -66,12 +69,15 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; +import jdk.vm.ci.hotspot.HotSpotSentinelConstant; import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -269,7 +275,7 @@ Register klass = r10; if (config.useCompressedClassPointers) { masm.ldr(32, klass, klassAddress); - AArch64HotSpotMove.decodeKlassPointer(masm, klass, klass, providers.getRegisters().getHeapBaseRegister(), config.getKlassEncoding()); + AArch64HotSpotMove.decodeKlassPointer(crb, masm, klass, klass, config.getKlassEncoding(), config); } else { masm.ldr(64, klass, klassAddress); } @@ -285,6 +291,23 @@ crb.recordMark(config.MARKID_OSR_ENTRY); masm.bind(verifiedStub); crb.recordMark(config.MARKID_VERIFIED_ENTRY); + + if (GeneratePIC.getValue(crb.getOptions())) { + // Check for method state + HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; + if (!frameContext.isStub) { + crb.recordInlineDataInCodeWithNote(new HotSpotSentinelConstant(LIRKind.value(AArch64Kind.QWORD), JavaKind.Long), HotSpotConstantLoadAction.MAKE_NOT_ENTRANT); + try (ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + masm.addressOf(scratch); + masm.ldr(64, scratch, AArch64Address.createBaseRegisterOnlyAddress(scratch)); + Label noCall = new Label(); + masm.cbz(64, scratch, noCall); + AArch64Call.directJmp(crb, masm, getForeignCalls().lookupForeignCall(WRONG_METHOD_HANDLER)); + masm.bind(noCall); + } + } + } } private static void emitCodeBody(CompilationResultBuilder crb, LIR lir, AArch64MacroAssembler masm) { @@ -299,8 +322,10 @@ * @see "http://mail.openjdk.java.net/pipermail/aarch64-port-dev/2013-September/000273.html" */ public static void emitInvalidatePlaceholder(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - crb.blockComment("[nop for method invalidation]"); - masm.nop(); + if (!GeneratePIC.getValue(crb.getOptions())) { + crb.blockComment("[nop for method invalidation]"); + masm.nop(); + } } private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler masm, FrameMap frameMap) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +26,10 @@ import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.common.InitTimer.timer; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse; @@ -64,10 +69,6 @@ import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.aarch64.AArch64; -import jdk.vm.ci.code.Architecture; -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; @@ -77,6 +78,9 @@ import jdk.vm.ci.meta.Value; import jdk.vm.ci.runtime.JVMCIBackend; +import java.util.ArrayList; +import java.util.List; + @ServiceProvider(HotSpotBackendFactory.class) public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { @@ -200,12 +204,20 @@ } protected static Value[] createNativeABICallerSaveRegisters(@SuppressWarnings("unused") GraalHotSpotVMConfig config, RegisterConfig regConfig) { - AArch64HotSpotRegisterConfig conf = (AArch64HotSpotRegisterConfig) regConfig; - RegisterArray callerSavedRegisters = conf.getCallerSaveRegisters(); - int size = callerSavedRegisters.size(); - Value[] nativeABICallerSaveRegisters = new Value[size]; - for (int i = 0; i < size; i++) { - nativeABICallerSaveRegisters[i] = callerSavedRegisters.get(i).asValue(); + List callerSave = new ArrayList<>(regConfig.getAllocatableRegisters().asList()); + callerSave.remove(AArch64.r19); + callerSave.remove(AArch64.r20); + callerSave.remove(AArch64.r21); + callerSave.remove(AArch64.r22); + callerSave.remove(AArch64.r23); + callerSave.remove(AArch64.r24); + callerSave.remove(AArch64.r25); + callerSave.remove(AArch64.r26); + callerSave.remove(AArch64.r27); + callerSave.remove(AArch64.r28); + Value[] nativeABICallerSaveRegisters = new Value[callerSave.size()]; + for (int i = 0; i < callerSave.size(); i++) { + nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue(); } return nativeABICallerSaveRegisters; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotCRuntimeCallEpilogueOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotCRuntimeCallEpilogueOp.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotCRuntimeCallEpilogueOp.java Thu May 31 13:39:26 2018 -0700 @@ -24,6 +24,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; @@ -37,20 +38,22 @@ public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotCRuntimeCallEpilogueOp.class); private final int threadLastJavaSpOffset; - private final int threadLastJavaFpOffset; + private final int threadLastJavaPcOffset; private final Register thread; + @SuppressWarnings("unused") private final Label label; - public AArch64HotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaFpOffset, Register thread) { + public AArch64HotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, Register thread, Label label) { super(TYPE); this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; this.thread = thread; + this.label = label; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { // Reset last Java frame: masm.str(64, zr, masm.makeAddress(thread, threadLastJavaSpOffset, 8)); - masm.str(64, zr, masm.makeAddress(thread, threadLastJavaFpOffset, 8)); + masm.str(64, zr, masm.makeAddress(thread, threadLastJavaPcOffset, 8)); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotCRuntimeCallPrologueOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotCRuntimeCallPrologueOp.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotCRuntimeCallPrologueOp.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +26,6 @@ import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; @@ -43,16 +43,14 @@ private final int threadLastJavaSpOffset; private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; private final Register thread; @Temp({REG}) protected AllocatableValue scratch; private final Label label; - public AArch64HotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, Register thread, AllocatableValue scratch, Label label) { + public AArch64HotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, Register thread, AllocatableValue scratch, Label label) { super(TYPE); this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; this.thread = thread; this.scratch = scratch; this.label = label; @@ -69,7 +67,5 @@ // Get the current PC. Use a label to patch the return address. masm.adr(scratchRegister, label); masm.str(64, scratchRegister, masm.makeAddress(thread, threadLastJavaPcOffset, 8)); - - masm.str(64, fp, masm.makeAddress(thread, threadLastJavaFpOffset, 8)); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotConstantRetrievalOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotConstantRetrievalOp.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import java.util.ArrayList; +import java.util.EnumSet; + +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.Value; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.LIRValueUtil; +import org.graalvm.compiler.lir.ValueProcedure; +import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +public final class AArch64HotSpotConstantRetrievalOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotConstantRetrievalOp.class); + + @Def protected AllocatableValue result; + protected final Constant[] constants; + @Alive protected AllocatableValue[] constantDescriptions; + @Temp protected AllocatableValue[] gotSlotOffsetParameters; + @Temp protected AllocatableValue[] descriptionParameters; + @Temp protected Value[] callTemps; + @State protected LIRFrameState frameState; + private final ForeignCallLinkage callLinkage; + private final Object[] notes; + + private class CollectTemporaries implements ValueProcedure { + ArrayList values = new ArrayList<>(); + + CollectTemporaries() { + forEachTemp(this); + } + + public Value[] asArray() { + Value[] copy = new Value[values.size()]; + return values.toArray(copy); + } + + @Override + public Value doValue(Value value, OperandMode mode, EnumSet flags) { + values.add(value); + return value; + } + } + + public AArch64HotSpotConstantRetrievalOp(Constant[] constants, AllocatableValue[] constantDescriptions, LIRFrameState frameState, ForeignCallLinkage callLinkage, Object[] notes) { + super(TYPE); + this.constantDescriptions = constantDescriptions; + this.constants = constants; + this.frameState = frameState; + this.notes = notes; + assert constants.length == notes.length; + + // call arguments + CallingConvention callingConvention = callLinkage.getOutgoingCallingConvention(); + this.gotSlotOffsetParameters = new AllocatableValue[constants.length]; + int argIndex = 0; + for (int i = 0; i < constants.length; i++, argIndex++) { + this.gotSlotOffsetParameters[i] = callingConvention.getArgument(argIndex); + } + this.descriptionParameters = new AllocatableValue[constantDescriptions.length]; + for (int i = 0; i < constantDescriptions.length; i++, argIndex++) { + this.descriptionParameters[i] = callingConvention.getArgument(argIndex); + } + this.result = callingConvention.getReturn(); + + this.callLinkage = callLinkage; + + // compute registers that are killed by the stub, but are not used as other temps. + this.callTemps = new Value[0]; + this.callTemps = LIRValueUtil.subtractRegisters(callLinkage.getTemporaries(), new CollectTemporaries().asArray()); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + // metadata_adr + for (int i = 0; i < constants.length; i++) { + crb.recordInlineDataInCodeWithNote(constants[i], notes[i]); + masm.addressOf(asRegister(gotSlotOffsetParameters[i])); + } + + for (int i = 0; i < constantDescriptions.length; i++) { + masm.mov(64, asRegister(descriptionParameters[i]), asRegister(constantDescriptions[i])); + } + + final int before = masm.position(); + masm.bl(before); + final int after = masm.position(); + crb.recordDirectCall(before, after, callLinkage, frameState); + } + +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +24,21 @@ package org.graalvm.compiler.hotspot.aarch64; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE; +import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE; +import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.INITIALIZE; +import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS; import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import java.util.function.Function; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; @@ -38,6 +49,7 @@ import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.GraalError; @@ -48,6 +60,7 @@ import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; +import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -66,6 +79,9 @@ import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; +import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp; +import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp; + import org.graalvm.compiler.lir.gen.LIRGenerationResult; import jdk.vm.ci.aarch64.AArch64; @@ -84,6 +100,7 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.Value; +import org.graalvm.compiler.options.OptionValues; /** * LIR generator specialized for AArch64 HotSpot. @@ -114,7 +131,7 @@ return getResult().getStub() != null; } - @SuppressWarnings("unused") private LIRFrameState currentRuntimeCallInfo; + private LIRFrameState currentRuntimeCallInfo; @Override protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { @@ -145,8 +162,45 @@ append(new AArch64CCall(nativeCallingConvention.getReturn(), ptr, argLocations)); } - public SaveRegistersOp emitSaveAllRegisters() { - throw GraalError.unimplemented(); + /** + * @param savedRegisters the registers saved by this operation which may be subject to pruning + * @param savedRegisterLocations the slots to which the registers are saved + * @param supportsRemove determines if registers can be pruned + */ + protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { + AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); + append(save); + return save; + } + + /** + * Allocate a stack slot for saving a register. + */ + protected VirtualStackSlot allocateSaveRegisterLocation(Register register) { + PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory()); + if (kind.getVectorLength() > 1) { + // we don't use vector registers, so there is no need to save them + kind = AArch64Kind.QWORD; + } + return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); + } + + /** + * Adds a node to the graph that saves all allocatable registers to the stack. + * + * @param supportsRemove determines if registers can be pruned + * @return the register save node + */ + private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) { + AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; + for (int i = 0; i < savedRegisters.length; i++) { + savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]); + } + return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); + } + + protected void emitRestoreRegisters(AArch64SaveRegistersOp save) { + append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save)); } @Override @@ -199,6 +253,7 @@ @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { LIRKind inputKind = pointer.getValueKind(LIRKind.class); + LIRKindTool lirKindTool = getLIRKindTool(); assert inputKind.getPlatformKind() == AArch64Kind.QWORD; if (inputKind.isReference(0)) { // oop @@ -209,8 +264,16 @@ // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.hasBase()) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { + Variable baseAddress = newVariable(lirKindTool.getWordKind()); + AArch64HotSpotMove.BaseMove move = new AArch64HotSpotMove.BaseMove(baseAddress, config); + append(move); + base = baseAddress; + } else { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); + } } append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -230,8 +293,16 @@ // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.hasBase()) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { + Variable baseAddress = newVariable(LIRKind.value(AArch64Kind.QWORD)); + AArch64HotSpotMove.BaseMove move = new AArch64HotSpotMove.BaseMove(baseAddress, config); + append(move); + base = baseAddress; + } else { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); + } } append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -270,6 +341,17 @@ @Override public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; + boolean destroysRegisters = hotspotLinkage.destroysRegisters(); + + AArch64SaveRegistersOp save = null; + Stub stub = getStub(); + if (destroysRegisters) { + if (stub != null && stub.preservesRegisters()) { + Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray(); + save = emitSaveAllRegisters(savedRegisters, true); + } + } + Variable result; LIRFrameState debugInfo = null; if (hotspotLinkage.needsDebugInfo()) { @@ -277,7 +359,7 @@ assert debugInfo != null || getStub() != null; } - if (linkage.destroysRegisters() || hotspotLinkage.needsJavaFrameAnchor()) { + if (destroysRegisters || hotspotLinkage.needsJavaFrameAnchor()) { HotSpotRegistersProvider registers = getProviders().getRegisters(); Register thread = registers.getThreadRegister(); Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind())); @@ -285,9 +367,9 @@ // We need a label for the return address. label = new Label(); - append(new AArch64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), thread, scratch, label)); + append(new AArch64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), thread, scratch, label)); result = super.emitForeignCall(hotspotLinkage, debugInfo, args); - append(new AArch64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); + append(new AArch64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), thread, label)); // Clear it out so it's not being reused later. label = null; @@ -295,6 +377,21 @@ result = super.emitForeignCall(hotspotLinkage, debugInfo, args); } + if (destroysRegisters) { + if (stub != null) { + if (stub.preservesRegisters()) { + HotSpotLIRGenerationResult generationResult = getResult(); + LIRFrameState key = currentRuntimeCallInfo; + if (key == null) { + key = LIRFrameState.NO_STATE; + } + assert !generationResult.getCalleeSaveInfo().containsKey(key); + generationResult.getCalleeSaveInfo().put(key, save); + emitRestoreRegisters(save); + } + } + } + return result; } @@ -336,6 +433,65 @@ } @Override + public Value emitLoadObjectAddress(Constant constant) { + HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; + LIRKind kind = objectConstant.isCompressed() ? getLIRKindTool().getNarrowOopKind() : getLIRKindTool().getObjectKind(); + Variable result = newVariable(kind); + append(new AArch64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); + return result; + } + + @Override + public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { + HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; + LIRKind kind = metaspaceConstant.isCompressed() ? getLIRKindTool().getNarrowPointerKind() : getLIRKindTool().getWordKind(); + Variable result = newVariable(kind); + append(new AArch64HotSpotLoadAddressOp(result, constant, action)); + return result; + } + + private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, Object[] notes, Constant[] constants, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { + ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(foreignCall); + append(new AArch64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); + AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); + return emitMove(result); + } + + private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { + Constant[] constants = new Constant[]{constant}; + Object[] notes = new Object[]{action}; + return emitConstantRetrieval(foreignCall, notes, constants, constantDescriptions, frameState); + } + + @Override + public Value emitResolveDynamicInvoke(Constant appendix, LIRFrameState frameState) { + AllocatableValue[] constantDescriptions = new AllocatableValue[0]; + return emitConstantRetrieval(RESOLVE_DYNAMIC_INVOKE, INITIALIZE, appendix, constantDescriptions, frameState); + } + + @Override + public Value emitLoadConfigValue(int markId, LIRKind kind) { + Variable result = newVariable(kind); + append(new AArch64HotSpotLoadConfigValueOp(markId, result)); + return result; + } + + private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, Value constantDescription, LIRFrameState frameState) { + AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; + return emitConstantRetrieval(foreignCall, action, constant, constantDescriptions, frameState); + } + + @Override + public Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { + return emitConstantRetrieval(RESOLVE_STRING_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); + } + + @Override + public Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { + return emitConstantRetrieval(RESOLVE_KLASS_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); + } + + @Override public void emitReturn(JavaKind kind, Value input) { AllocatableValue operand = Value.ILLEGAL; if (input != null) { @@ -346,6 +502,17 @@ append(new AArch64HotSpotReturnOp(operand, getStub() != null, config, thread)); } + @Override + public Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { + return emitConstantRetrieval(INITIALIZE_KLASS_BY_SYMBOL, INITIALIZE, constant, constantDescription, frameState); + } + + @Override + public Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) { + AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(klassHint), asAllocatable(methodDescription)}; + return emitConstantRetrieval(RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, LOAD_COUNTERS, method, constantDescriptions, frameState); + } + /** * Gets the {@link Stub} this generator is generating code for or {@code null} if a stub is not * being generated. diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadAddressOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadAddressOp.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Constant; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +public final class AArch64HotSpotLoadAddressOp extends AArch64LIRInstruction { + + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotLoadAddressOp.class); + + @Def({OperandFlag.REG}) protected AllocatableValue result; + private final Constant constant; + private final Object note; + + public AArch64HotSpotLoadAddressOp(AllocatableValue result, Constant constant, Object note) { + super(TYPE); + this.result = result; + this.constant = constant; + this.note = note; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + crb.recordInlineDataInCodeWithNote(constant, note); + AArch64Kind kind = (AArch64Kind) result.getPlatformKind(); + int size = 0; + switch (kind) { + case DWORD: + size = 32; + break; + case QWORD: + size = 64; + break; + default: + throw GraalError.shouldNotReachHere("unexpected kind: " + kind); + } + if (crb.compilationResult.isImmutablePIC()) { + Register dst = asRegister(result); + masm.addressOf(dst); + masm.ldr(size, dst, AArch64Address.createBaseRegisterOnlyAddress(dst)); + } else { + masm.ldr(size, asRegister(result), masm.getPlaceholder(-1)); + } + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadConfigValueOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadConfigValueOp.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +public final class AArch64HotSpotLoadConfigValueOp extends AArch64LIRInstruction { + + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotLoadConfigValueOp.class); + + @Def({OperandFlag.REG}) protected AllocatableValue result; + private final int markId; + + public AArch64HotSpotLoadConfigValueOp(int markId, AllocatableValue result) { + super(TYPE); + this.result = result; + this.markId = markId; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + if (GeneratePIC.getValue(crb.getOptions())) { + AArch64Kind kind = (AArch64Kind) result.getPlatformKind(); + Register reg = asRegister(result); + masm.adrp(reg); + masm.add(64, reg, reg, 1); + switch (kind) { + case BYTE: + masm.ldrs(8, 32, reg, AArch64Address.createBaseRegisterOnlyAddress(reg)); + break; + case WORD: + masm.ldrs(16, 32, reg, AArch64Address.createBaseRegisterOnlyAddress(reg)); + break; + case DWORD: + masm.ldr(32, reg, AArch64Address.createBaseRegisterOnlyAddress(reg)); + break; + case QWORD: + masm.ldr(64, reg, AArch64Address.createBaseRegisterOnlyAddress(reg)); + break; + default: + throw GraalError.unimplemented(); + } + masm.nop(); + } else { + throw GraalError.unimplemented(); + } + crb.recordMark(markId); + } + +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java Thu May 31 13:39:26 2018 -0700 @@ -26,13 +26,13 @@ import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; +import org.graalvm.compiler.nodes.calc.IntegerDivRemNode; import org.graalvm.compiler.nodes.calc.RemNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; @@ -62,8 +62,8 @@ @Override public void lower(Node n, LoweringTool tool) { - if (n instanceof FixedBinaryNode) { - integerArithmeticSnippets.lower((FixedBinaryNode) n, tool); + if (n instanceof IntegerDivRemNode) { + integerArithmeticSnippets.lower((IntegerDivRemNode) n, tool); } else if (n instanceof RemNode) { floatArithmeticSnippets.lower((RemNode) n, tool); } else if (n instanceof FloatConvertNode) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java Thu May 31 13:39:26 2018 -0700 @@ -25,15 +25,19 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -80,6 +84,32 @@ } } + public static final class BaseMove extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BaseMove.class); + + @LIRInstruction.Def({REG, HINT}) protected AllocatableValue result; + private final GraalHotSpotVMConfig config; + + public BaseMove(AllocatableValue result, GraalHotSpotVMConfig config) { + super(TYPE); + this.result = result; + this.config = config; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + try (AArch64MacroAssembler.ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + masm.adrp(scratch); + masm.add(64, scratch, scratch, 1); + masm.ldr(64, asRegister(result), AArch64Address.createBaseRegisterOnlyAddress(scratch)); + masm.nop(); + crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); + } + } + + } + /** * Compresses a 8-byte pointer as a 4-byte int. */ @@ -117,7 +147,7 @@ } else if (nonNull) { masm.sub(64, resultRegister, ptr, base); if (encoding.hasShift()) { - masm.shl(64, resultRegister, resultRegister, encoding.getShift()); + masm.lshr(64, resultRegister, resultRegister, encoding.getShift()); } } else { // if ptr is null it still has to be null after compression @@ -192,11 +222,21 @@ // masm.cmov(64, result, result, ARMv8.zr, ARMv8Assembler.ConditionFlag.NE); // } - public static void decodeKlassPointer(AArch64MacroAssembler masm, Register result, Register ptr, Register klassBase, CompressEncoding encoding) { - // result = klassBase + ptr << shift - if (encoding.hasShift() || encoding.hasBase()) { - masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); + public static void decodeKlassPointer(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, Register ptr, CompressEncoding encoding, GraalHotSpotVMConfig config) { + try (AArch64MacroAssembler.ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + boolean pic = GeneratePIC.getValue(crb.getOptions()); + if (pic || encoding.hasBase() || encoding.getShift() != 0) { + if (pic) { + masm.addressOf(scratch); + masm.ldr(64, scratch, AArch64Address.createBaseRegisterOnlyAddress(scratch)); + masm.add(64, result, scratch, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); + crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); + } else { + masm.mov(scratch, encoding.getBase()); + masm.add(64, result, scratch, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); + } + } } } - } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java Thu May 31 13:39:26 2018 -0700 @@ -236,7 +236,7 @@ } @Override - public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); SPARCKind memKind = (SPARCKind) kind.getPlatformKind(); @@ -246,7 +246,7 @@ } @Override - public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + public Variable emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); Variable result = newVariable(newValue.getValueKind()); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Thu May 31 13:39:26 2018 -0700 @@ -422,6 +422,12 @@ "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I"); } + if (isJDK11OrHigher()) { + // Relevant for Java flight recorder + add(TO_BE_INVESTIGATED, + "jdk/jfr/internal/JVM.getEventWriter()Ljava/lang/Object;"); + } + if (!getHostArchitectureName().equals("amd64")) { // Can we implement these on non-AMD64 platforms? C2 seems to. add(TO_BE_INVESTIGATED, @@ -549,6 +555,10 @@ return GraalServices.JAVA_SPECIFICATION_VERSION >= 10; } + private static boolean isJDK11OrHigher() { + return GraalServices.JAVA_SPECIFICATION_VERSION >= 11; + } + private static String getHostArchitectureName() { String arch = System.getProperty("os.arch"); if (arch.equals("x86_64")) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java Thu May 31 13:39:26 2018 -0700 @@ -223,25 +223,19 @@ Assert.assertTrue(zip.toString(), zip.exists()); Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName())); try { - int bgv = 0; - int cfg = 0; + int bgvOrCfgFiles = 0; ZipFile dd = new ZipFile(diagnosticOutputZip); List entries = new ArrayList<>(); for (Enumeration e = dd.entries(); e.hasMoreElements();) { ZipEntry ze = e.nextElement(); String name = ze.getName(); entries.add(name); - if (name.endsWith(".bgv")) { - bgv++; - } else if (name.endsWith(".cfg")) { - cfg++; + if (name.endsWith(".bgv") || name.endsWith(".cfg")) { + bgvOrCfgFiles++; } } - if (bgv == 0) { - Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc)); - } - if (cfg == 0) { - Assert.fail(String.format("Expected at least one .cfg file in %s: %s%n%s", diagnosticOutputZip, entries, proc)); + if (bgvOrCfgFiles == 0) { + Assert.fail(String.format("Expected at least one .bgv or .cfg file in %s: %s%n%s", diagnosticOutputZip, entries, proc)); } } finally { zip.delete(); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/aaa --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/aaa Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.java.GraphBuilderPhase; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class HotSpotLazyInitializationTest extends GraalCompilerTest { - - HotSpotClassInitializationPlugin classInitPlugin = new HotSpotClassInitializationPlugin(); - - @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - plugins.setClassInitializationPlugin(classInitPlugin); - return plugins; - } - - static boolean X_initialized = false; - - static class X { - static { - X_initialized = true; - } - static void foo() {} - } - - public static void invokeStatic() { - X.foo(); - } - - private void test(String name) { - ResolvedJavaMethod method = getResolvedJavaMethod(name); - Assume.assumeTrue("skipping for old JVMCI", classInitPlugin.supportsLazyInitialization(method.getConstantPool())); - StructuredGraph graph = parseEager(method, AllowAssumptions.NO); - Assert.assertFalse(X_initialized); - } - - @Test - public void test1() { - test("invokeStatic"); - } - -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Thu May 31 13:39:26 2018 -0700 @@ -101,6 +101,13 @@ return new DefaultBackendMap(name); } + /** + * Returns a name that should uniquely identify this compiler configuration. + */ + public final String getName() { + return name; + } + public interface BackendMap { HotSpotBackendFactory getBackendFactory(Architecture arch); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu May 31 13:39:26 2018 -0700 @@ -80,6 +80,9 @@ public final boolean foldStableValues = getFlag("FoldStableValues", Boolean.class); public final int maxVectorSize = getFlag("MaxVectorSize", Integer.class); + public final boolean verifyBeforeGC = getFlag("VerifyBeforeGC", Boolean.class); + public final boolean verifyAfterGC = getFlag("VerifyAfterGC", Boolean.class); + public final boolean useTLAB = getFlag("UseTLAB", Boolean.class); public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class); public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java Thu May 31 13:39:26 2018 -0700 @@ -40,12 +40,12 @@ super(store); } + // JSK-8132287 + final boolean inlineNotify = !getFlag("SyncKnobs", String.class, "").contains("InlineNotify=0"); + // JDK-8073583 final boolean useCRC32CIntrinsics = getFlag("UseCRC32CIntrinsics", Boolean.class); - // JDK-8075171 - final boolean inlineNotify = getFlag("InlineNotify", Boolean.class, true); - // JDK-8046936 final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address"); final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u2"); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu May 31 13:39:26 2018 -0700 @@ -185,7 +185,7 @@ result.setEntryBCI(entryBCI); boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints(); PhaseSuite graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR); - GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf); + GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf, true); if (!isOSR && useProfilingInfo) { ProfilingInfo profile = profilingInfo; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu May 31 13:39:26 2018 -0700 @@ -105,6 +105,7 @@ } private final String runtimeName; + private final String compilerConfigurationName; private final HotSpotBackend hostBackend; private final GlobalMetrics metricValues = new GlobalMetrics(); private final List snippetCounterGroups; @@ -155,6 +156,7 @@ compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration(); + compilerConfigurationName = compilerConfigurationFactory.getName(); compiler = new HotSpotGraalCompiler(jvmciRuntime, this, options); management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false); @@ -296,6 +298,11 @@ return backends.get(arch); } + @Override + public String getCompilerConfigurationName() { + return compilerConfigurationName; + } + private long runtimeStartTime; private boolean shutdown; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Thu May 31 13:39:26 2018 -0700 @@ -94,4 +94,10 @@ * Gets the map used to count compilation problems at each {@link ExceptionAction} level. */ Map getCompilationProblemsPerAction(); + + /** + * Returns the unique compiler configuration name that is in use. Useful for users to find out + * which configuration is in use. + */ + String getCompilerConfigurationName(); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import static jdk.internal.vm.compiler.word.LocationIdentity.any; import java.lang.ref.Reference; +import java.util.EnumMap; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.common.CompressEncoding; @@ -49,6 +50,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; @@ -91,8 +93,8 @@ import org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets; import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyNode; +import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets; import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyWithSlowPathNode; -import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets; import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -118,6 +120,7 @@ import org.graalvm.compiler.nodes.debug.StringToBytesNode; import org.graalvm.compiler.nodes.debug.VerifyHeapNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode; @@ -207,7 +210,7 @@ instanceofSnippets = new InstanceOfSnippets.Templates(options, factories, runtime, providers, target); newObjectSnippets = new NewObjectSnippets.Templates(options, factories, runtime, providers, target, config); monitorSnippets = new MonitorSnippets.Templates(options, factories, runtime, providers, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, factories, providers, target); unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, factories, providers, target); assertionSnippets = new AssertionSnippets.Templates(options, factories, providers, target); @@ -223,162 +226,165 @@ } @Override + @SuppressWarnings("try") public void lower(Node n, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) n.graph(); - if (n instanceof Invoke) { - lowerInvoke((Invoke) n, tool, graph); - } else if (n instanceof LoadMethodNode) { - lowerLoadMethodNode((LoadMethodNode) n); - } else if (n instanceof GetClassNode) { - lowerGetClassNode((GetClassNode) n, tool, graph); - } else if (n instanceof StoreHubNode) { - lowerStoreHubNode((StoreHubNode) n, graph); - } else if (n instanceof OSRStartNode) { - lowerOSRStartNode((OSRStartNode) n); - } else if (n instanceof BytecodeExceptionNode) { - lowerBytecodeExceptionNode((BytecodeExceptionNode) n); - } else if (n instanceof InstanceOfNode) { - InstanceOfNode instanceOfNode = (InstanceOfNode) n; - if (graph.getGuardsStage().areDeoptsFixed()) { - instanceofSnippets.lower(instanceOfNode, tool); - } else { - if (instanceOfNode.allowsNull()) { - ValueNode object = instanceOfNode.getValue(); - LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfNode.create(instanceOfNode.type(), object, instanceOfNode.profile(), instanceOfNode.getAnchor())); - LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY); - instanceOfNode.replaceAndDelete(newNode); + try (DebugCloseable context = n.withNodeSourcePosition()) { + if (n instanceof Invoke) { + lowerInvoke((Invoke) n, tool, graph); + } else if (n instanceof LoadMethodNode) { + lowerLoadMethodNode((LoadMethodNode) n); + } else if (n instanceof GetClassNode) { + lowerGetClassNode((GetClassNode) n, tool, graph); + } else if (n instanceof StoreHubNode) { + lowerStoreHubNode((StoreHubNode) n, graph); + } else if (n instanceof OSRStartNode) { + lowerOSRStartNode((OSRStartNode) n); + } else if (n instanceof BytecodeExceptionNode) { + lowerBytecodeExceptionNode((BytecodeExceptionNode) n); + } else if (n instanceof InstanceOfNode) { + InstanceOfNode instanceOfNode = (InstanceOfNode) n; + if (graph.getGuardsStage().areDeoptsFixed()) { + instanceofSnippets.lower(instanceOfNode, tool); + } else { + if (instanceOfNode.allowsNull()) { + ValueNode object = instanceOfNode.getValue(); + LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfNode.create(instanceOfNode.type(), object, instanceOfNode.profile(), instanceOfNode.getAnchor())); + LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY); + instanceOfNode.replaceAndDelete(newNode); + } } - } - } else if (n instanceof InstanceOfDynamicNode) { - InstanceOfDynamicNode instanceOfDynamicNode = (InstanceOfDynamicNode) n; - if (graph.getGuardsStage().areDeoptsFixed()) { - instanceofSnippets.lower(instanceOfDynamicNode, tool); - } else { - ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub(); - if (mirror.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Object) { - ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror)); - instanceOfDynamicNode.setMirror(classGetHub); - } + } else if (n instanceof InstanceOfDynamicNode) { + InstanceOfDynamicNode instanceOfDynamicNode = (InstanceOfDynamicNode) n; + if (graph.getGuardsStage().areDeoptsFixed()) { + instanceofSnippets.lower(instanceOfDynamicNode, tool); + } else { + ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub(); + if (mirror.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Object) { + ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror)); + instanceOfDynamicNode.setMirror(classGetHub); + } - if (instanceOfDynamicNode.allowsNull()) { - ValueNode object = instanceOfDynamicNode.getObject(); - LogicNode newTypeCheck = graph.addOrUniqueWithInputs( - InstanceOfDynamicNode.create(graph.getAssumptions(), tool.getConstantReflection(), instanceOfDynamicNode.getMirrorOrHub(), object, false)); - LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY); - instanceOfDynamicNode.replaceAndDelete(newNode); + if (instanceOfDynamicNode.allowsNull()) { + ValueNode object = instanceOfDynamicNode.getObject(); + LogicNode newTypeCheck = graph.addOrUniqueWithInputs( + InstanceOfDynamicNode.create(graph.getAssumptions(), tool.getConstantReflection(), instanceOfDynamicNode.getMirrorOrHub(), object, false)); + LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY); + instanceOfDynamicNode.replaceAndDelete(newNode); + } + } + } else if (n instanceof ClassIsAssignableFromNode) { + if (graph.getGuardsStage().areDeoptsFixed()) { + instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool); + } + } else if (n instanceof NewInstanceNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + newObjectSnippets.lower((NewInstanceNode) n, registers, tool); + } + } else if (n instanceof DynamicNewInstanceNode) { + DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n; + if (newInstanceNode.getClassClass() == null) { + JavaConstant classClassMirror = constantReflection.forObject(Class.class); + ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph); + newInstanceNode.setClassClass(classClass); + } + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + newObjectSnippets.lower(newInstanceNode, registers, tool); + } + } else if (n instanceof NewArrayNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + newObjectSnippets.lower((NewArrayNode) n, registers, tool); + } + } else if (n instanceof DynamicNewArrayNode) { + DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n; + if (dynamicNewArrayNode.getVoidClass() == null) { + JavaConstant voidClassMirror = constantReflection.forObject(void.class); + ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph); + dynamicNewArrayNode.setVoidClass(voidClass); + } + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + newObjectSnippets.lower(dynamicNewArrayNode, registers, tool); + } + } else if (n instanceof VerifyHeapNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + newObjectSnippets.lower((VerifyHeapNode) n, registers, tool); + } + } else if (n instanceof RawMonitorEnterNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + monitorSnippets.lower((RawMonitorEnterNode) n, registers, tool); + } + } else if (n instanceof MonitorExitNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + monitorSnippets.lower((MonitorExitNode) n, registers, tool); } - } - } else if (n instanceof ClassIsAssignableFromNode) { - if (graph.getGuardsStage().areDeoptsFixed()) { - instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool); - } - } else if (n instanceof NewInstanceNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - newObjectSnippets.lower((NewInstanceNode) n, registers, tool); - } - } else if (n instanceof DynamicNewInstanceNode) { - DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n; - if (newInstanceNode.getClassClass() == null) { - JavaConstant classClassMirror = constantReflection.forObject(Class.class); - ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph); - newInstanceNode.setClassClass(classClass); - } - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - newObjectSnippets.lower(newInstanceNode, registers, tool); - } - } else if (n instanceof NewArrayNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - newObjectSnippets.lower((NewArrayNode) n, registers, tool); - } - } else if (n instanceof DynamicNewArrayNode) { - DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n; - if (dynamicNewArrayNode.getVoidClass() == null) { - JavaConstant voidClassMirror = constantReflection.forObject(void.class); - ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph); - dynamicNewArrayNode.setVoidClass(voidClass); - } - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - newObjectSnippets.lower(dynamicNewArrayNode, registers, tool); + } else if (n instanceof ArrayCopyNode) { + arraycopySnippets.lower((ArrayCopyNode) n, tool); + } else if (n instanceof ArrayCopyWithSlowPathNode) { + arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool); + } else if (n instanceof G1PreWriteBarrier) { + writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool); + } else if (n instanceof G1PostWriteBarrier) { + writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool); + } else if (n instanceof G1ReferentFieldReadBarrier) { + writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool); + } else if (n instanceof SerialWriteBarrier) { + writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); + } else if (n instanceof SerialArrayRangeWriteBarrier) { + writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); + } else if (n instanceof G1ArrayRangePreWriteBarrier) { + writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool); + } else if (n instanceof G1ArrayRangePostWriteBarrier) { + writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool); + } else if (n instanceof NewMultiArrayNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + newObjectSnippets.lower((NewMultiArrayNode) n, tool); + } + } else if (n instanceof LoadExceptionObjectNode) { + exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); + } else if (n instanceof AssertionNode) { + assertionSnippets.lower((AssertionNode) n, tool); + } else if (n instanceof StringToBytesNode) { + if (graph.getGuardsStage().areDeoptsFixed()) { + stringToBytesSnippets.lower((StringToBytesNode) n, tool); + } + } else if (n instanceof IntegerDivRemNode) { + // Nothing to do for division nodes. The HotSpot signal handler catches divisions by + // zero and the MIN_VALUE / -1 cases. + } else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode || n instanceof SafepointNode) { + /* No lowering, we generate LIR directly for these nodes. */ + } else if (n instanceof ClassGetHubNode) { + lowerClassGetHubNode((ClassGetHubNode) n, tool); + } else if (n instanceof HubGetClassNode) { + lowerHubGetClassNode((HubGetClassNode) n, tool); + } else if (n instanceof KlassLayoutHelperNode) { + lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool); + } else if (n instanceof ComputeObjectAddressNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + lowerComputeObjectAddressNode((ComputeObjectAddressNode) n); + } + } else if (n instanceof IdentityHashCodeNode) { + hashCodeSnippets.lower((IdentityHashCodeNode) n, tool); + } else if (n instanceof ResolveDynamicConstantNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveDynamicConstantNode) n, tool); + } + } else if (n instanceof ResolveConstantNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveConstantNode) n, tool); + } + } else if (n instanceof ResolveMethodAndLoadCountersNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); + } + } else if (n instanceof InitializeKlassNode) { + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((InitializeKlassNode) n, tool); + } + } else if (n instanceof ProfileNode) { + profileSnippets.lower((ProfileNode) n, tool); + } else { + super.lower(n, tool); } - } else if (n instanceof VerifyHeapNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - newObjectSnippets.lower((VerifyHeapNode) n, registers, tool); - } - } else if (n instanceof RawMonitorEnterNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - monitorSnippets.lower((RawMonitorEnterNode) n, registers, tool); - } - } else if (n instanceof MonitorExitNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - monitorSnippets.lower((MonitorExitNode) n, registers, tool); - } - } else if (n instanceof ArrayCopyNode) { - arraycopySnippets.lower((ArrayCopyNode) n, tool); - } else if (n instanceof ArrayCopyWithSlowPathNode) { - arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool); - } else if (n instanceof G1PreWriteBarrier) { - writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool); - } else if (n instanceof G1PostWriteBarrier) { - writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool); - } else if (n instanceof G1ReferentFieldReadBarrier) { - writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool); - } else if (n instanceof SerialWriteBarrier) { - writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); - } else if (n instanceof SerialArrayRangeWriteBarrier) { - writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); - } else if (n instanceof G1ArrayRangePreWriteBarrier) { - writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool); - } else if (n instanceof G1ArrayRangePostWriteBarrier) { - writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool); - } else if (n instanceof NewMultiArrayNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - newObjectSnippets.lower((NewMultiArrayNode) n, tool); - } - } else if (n instanceof LoadExceptionObjectNode) { - exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); - } else if (n instanceof AssertionNode) { - assertionSnippets.lower((AssertionNode) n, tool); - } else if (n instanceof StringToBytesNode) { - if (graph.getGuardsStage().areDeoptsFixed()) { - stringToBytesSnippets.lower((StringToBytesNode) n, tool); - } - } else if (n instanceof IntegerDivRemNode) { - // Nothing to do for division nodes. The HotSpot signal handler catches divisions by - // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode || n instanceof SafepointNode) { - /* No lowering, we generate LIR directly for these nodes. */ - } else if (n instanceof ClassGetHubNode) { - lowerClassGetHubNode((ClassGetHubNode) n, tool); - } else if (n instanceof HubGetClassNode) { - lowerHubGetClassNode((HubGetClassNode) n, tool); - } else if (n instanceof KlassLayoutHelperNode) { - lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool); - } else if (n instanceof ComputeObjectAddressNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - lowerComputeObjectAddressNode((ComputeObjectAddressNode) n); - } - } else if (n instanceof IdentityHashCodeNode) { - hashCodeSnippets.lower((IdentityHashCodeNode) n, tool); - } else if (n instanceof ResolveDynamicConstantNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((ResolveDynamicConstantNode) n, tool); - } - } else if (n instanceof ResolveConstantNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((ResolveConstantNode) n, tool); - } - } else if (n instanceof ResolveMethodAndLoadCountersNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); - } - } else if (n instanceof InitializeKlassNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((InitializeKlassNode) n, tool); - } - } else if (n instanceof ProfileNode) { - profileSnippets.lower((ProfileNode) n, tool); - } else { - super.lower(n, tool); } } @@ -635,59 +641,53 @@ } static final class Exceptions { - protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException; - protected static final NullPointerException cachedNullPointerException; + protected static final EnumMap cachedExceptions; static { - cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException(); - cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]); - cachedNullPointerException = new NullPointerException(); - cachedNullPointerException.setStackTrace(new StackTraceElement[0]); + cachedExceptions = new EnumMap<>(BytecodeExceptionKind.class); + cachedExceptions.put(BytecodeExceptionKind.NULL_POINTER, clearStackTrace(new NullPointerException())); + cachedExceptions.put(BytecodeExceptionKind.OUT_OF_BOUNDS, clearStackTrace(new ArrayIndexOutOfBoundsException())); + cachedExceptions.put(BytecodeExceptionKind.CLASS_CAST, clearStackTrace(new ClassCastException())); + cachedExceptions.put(BytecodeExceptionKind.ARRAY_STORE, clearStackTrace(new ArrayStoreException())); + cachedExceptions.put(BytecodeExceptionKind.DIVISION_BY_ZERO, clearStackTrace(new ArithmeticException())); + } + + private static RuntimeException clearStackTrace(RuntimeException ex) { + ex.setStackTrace(new StackTraceElement[0]); + return ex; } } public static final class RuntimeCalls { - public static final ForeignCallDescriptor CREATE_ARRAY_STORE_EXCEPTION = new ForeignCallDescriptor("createArrayStoreException", ArrayStoreException.class, Object.class); - public static final ForeignCallDescriptor CREATE_CLASS_CAST_EXCEPTION = new ForeignCallDescriptor("createClassCastException", ClassCastException.class, Object.class, KlassPointer.class); - public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class); - public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class); + public static final EnumMap runtimeCalls; + + static { + runtimeCalls = new EnumMap<>(BytecodeExceptionKind.class); + runtimeCalls.put(BytecodeExceptionKind.ARRAY_STORE, new ForeignCallDescriptor("createArrayStoreException", ArrayStoreException.class, Object.class)); + runtimeCalls.put(BytecodeExceptionKind.CLASS_CAST, new ForeignCallDescriptor("createClassCastException", ClassCastException.class, Object.class, KlassPointer.class)); + runtimeCalls.put(BytecodeExceptionKind.NULL_POINTER, new ForeignCallDescriptor("createNullPointerException", NullPointerException.class)); + runtimeCalls.put(BytecodeExceptionKind.OUT_OF_BOUNDS, new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class, int.class)); + runtimeCalls.put(BytecodeExceptionKind.DIVISION_BY_ZERO, new ForeignCallDescriptor("createDivisionByZeroException", ArithmeticException.class)); + } } - private boolean throwCachedException(BytecodeExceptionNode node) { - Throwable exception; - if (node.getExceptionClass() == NullPointerException.class) { - exception = Exceptions.cachedNullPointerException; - } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) { - exception = Exceptions.cachedArrayIndexOutOfBoundsException; - } else { - return false; - } + private void throwCachedException(BytecodeExceptionNode node) { + Throwable exception = Exceptions.cachedExceptions.get(node.getExceptionKind()); + assert exception != null; StructuredGraph graph = node.graph(); FloatingNode exceptionNode = ConstantNode.forConstant(constantReflection.forObject(exception), metaAccess, graph); graph.replaceFixedWithFloating(node, exceptionNode); - return true; } private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) { if (OmitHotExceptionStacktrace.getValue(node.getOptions())) { - if (throwCachedException(node)) { - return; - } + throwCachedException(node); + return; } - ForeignCallDescriptor descriptor; - if (node.getExceptionClass() == NullPointerException.class) { - descriptor = RuntimeCalls.CREATE_NULL_POINTER_EXCEPTION; - } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) { - descriptor = RuntimeCalls.CREATE_OUT_OF_BOUNDS_EXCEPTION; - } else if (node.getExceptionClass() == ArrayStoreException.class) { - descriptor = RuntimeCalls.CREATE_ARRAY_STORE_EXCEPTION; - } else if (node.getExceptionClass() == ClassCastException.class) { - descriptor = RuntimeCalls.CREATE_CLASS_CAST_EXCEPTION; - } else { - throw GraalError.shouldNotReachHere(); - } + ForeignCallDescriptor descriptor = RuntimeCalls.runtimeCalls.get(node.getExceptionKind()); + assert descriptor != null; StructuredGraph graph = node.graph(); ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(NodeView.DEFAULT), node.getArguments())); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu May 31 13:39:26 2018 -0700 @@ -65,10 +65,6 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.STACK_INSPECTABLE_LEAF; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.CREATE_ARRAY_STORE_EXCEPTION; -import static org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.CREATE_CLASS_CAST_EXCEPTION; -import static org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.CREATE_NULL_POINTER_EXCEPTION; -import static org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.CREATE_OUT_OF_BOUNDS_EXCEPTION; import static org.graalvm.compiler.hotspot.replacements.AssertionSnippets.ASSERTION_VM_MESSAGE_C; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION; @@ -112,6 +108,7 @@ import org.graalvm.compiler.hotspot.stubs.ArrayStoreExceptionStub; import org.graalvm.compiler.hotspot.stubs.ClassCastExceptionStub; import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub; +import org.graalvm.compiler.hotspot.stubs.DivisionByZeroExceptionStub; import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub; import org.graalvm.compiler.hotspot.stubs.NewArrayStub; import org.graalvm.compiler.hotspot.stubs.NewInstanceStub; @@ -121,6 +118,7 @@ import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; import org.graalvm.compiler.hotspot.stubs.VerifyOopStub; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; @@ -285,10 +283,13 @@ link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER))); link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); - link(new ArrayStoreExceptionStub(options, providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new ClassCastExceptionStub(options, providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new NullPointerExceptionStub(options, providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + + EnumMap exceptionRuntimeCalls = DefaultHotSpotLoweringProvider.RuntimeCalls.runtimeCalls; + link(new ArrayStoreExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.ARRAY_STORE), REEXECUTABLE, SAFEPOINT, any()))); + link(new ClassCastExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.CLASS_CAST), REEXECUTABLE, SAFEPOINT, any()))); + link(new NullPointerExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.NULL_POINTER), REEXECUTABLE, SAFEPOINT, any()))); + link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.OUT_OF_BOUNDS), REEXECUTABLE, SAFEPOINT, any()))); + link(new DivisionByZeroExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.DIVISION_BY_ZERO), REEXECUTABLE, SAFEPOINT, any()))); linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java Thu May 31 13:39:26 2018 -0700 @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderTool; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; @@ -147,16 +148,16 @@ } @Override - public boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind) { - if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadIndexed(b, array, index, elementKind)) { + public boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { + if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadIndexed(b, array, index, boundsCheck, elementKind)) { return true; } return false; } @Override - public boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind, ValueNode value) { - if (b.parsingIntrinsic() && wordOperationPlugin.handleStoreIndexed(b, array, index, elementKind, value)) { + public boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind elementKind, ValueNode value) { + if (b.parsingIntrinsic() && wordOperationPlugin.handleStoreIndexed(b, array, index, boundsCheck, storeCheck, elementKind, value)) { return true; } return false; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -45,6 +45,7 @@ import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.calc.PointerEqualsNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; @@ -69,13 +70,13 @@ } @Override - protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) { + protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index, GuardingNode boundsCheck) { ResolvedJavaType arrayType = StampTool.typeOrNull(array); Stamp componentStamp = wordTypes.getWordStamp(arrayType.getComponentType()); if (componentStamp instanceof MetaspacePointerStamp) { - return new LoadIndexedPointerNode(componentStamp, array, index); + return new LoadIndexedPointerNode(componentStamp, array, index, boundsCheck); } else { - return super.createLoadIndexedNode(array, index); + return super.createLoadIndexedNode(array, index, boundsCheck); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LoadIndexedPointerNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LoadIndexedPointerNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LoadIndexedPointerNode.java Thu May 31 13:39:26 2018 -0700 @@ -26,6 +26,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import jdk.vm.ci.meta.JavaKind; @@ -35,8 +36,8 @@ public static final NodeClass TYPE = NodeClass.create(LoadIndexedPointerNode.class); - public LoadIndexedPointerNode(Stamp stamp, ValueNode array, ValueNode index) { - super(TYPE, stamp, array, index, JavaKind.Illegal); + public LoadIndexedPointerNode(Stamp stamp, ValueNode array, ValueNode index, GuardingNode boundsCheck) { + super(TYPE, stamp, array, index, boundsCheck, JavaKind.Illegal); } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Thu May 31 13:39:26 2018 -0700 @@ -121,6 +121,8 @@ boolean precise = barrierType == BarrierType.PRECISE; if (config.useG1GC) { if (!node.getLocationIdentity().isInit()) { + // The pre barrier does nothing if the value being read is null, so it can + // be explicitly skipped when this is an initializing store. addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph); } addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph); @@ -178,6 +180,8 @@ private void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) { if (config.useG1GC) { if (!write.isInitialization()) { + // The pre barrier does nothing if the value being read is null, so it can + // be explicitly skipped when this is an initializing store. G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride())); graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java Thu May 31 13:39:26 2018 -0700 @@ -40,10 +40,8 @@ import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; -import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.Replacements; -import org.graalvm.compiler.nodes.spi.VirtualizableAllocation; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.replacements.nodes.BasicObjectCloneNode; @@ -53,7 +51,7 @@ import jdk.vm.ci.meta.ResolvedJavaType; @NodeInfo -public final class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider { +public final class ObjectCloneNode extends BasicObjectCloneNode { public static final NodeClass TYPE = NodeClass.create(ObjectCloneNode.class); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Thu May 31 13:39:26 2018 -0700 @@ -51,6 +51,7 @@ import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; @@ -65,6 +66,7 @@ import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; @@ -79,12 +81,14 @@ import org.graalvm.compiler.nodes.type.NarrowOopStamp; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.Log; +import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; +import org.graalvm.compiler.replacements.nodes.AssertionNode; import org.graalvm.compiler.replacements.nodes.DirectStoreNode; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; @@ -140,7 +144,10 @@ } @Snippet - public static void serialImpreciseWriteBarrier(Object object, @ConstantParameter Counters counters) { + public static void serialImpreciseWriteBarrier(Object object, @ConstantParameter boolean verifyBarrier, @ConstantParameter Counters counters) { + if (verifyBarrier) { + verifyNotArray(object); + } serialWriteBarrier(Word.objectToTrackedPointer(object), counters); } @@ -221,8 +228,8 @@ } @Snippet - public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter Register threadRegister, - @ConstantParameter boolean trace, @ConstantParameter Counters counters) { + public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter boolean verifyBarrier, + @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, @ConstantParameter Counters counters) { Word thread = registerAsWord(threadRegister); Object fixedValue = FixedValueAnchorNode.getObject(value); verifyOop(object); @@ -232,6 +239,9 @@ if (usePrecise) { oop = Word.fromAddress(address); } else { + if (verifyBarrier) { + verifyNotArray(object); + } oop = Word.objectToTrackedPointer(object); } int gcCycle = 0; @@ -298,6 +308,13 @@ } } + private static void verifyNotArray(Object object) { + if (object != null) { + // Manually build the null check and cast because we're in snippet that's lowered late. + AssertionNode.assertion(false, !PiNode.piCastNonNull(object, Object.class).getClass().isArray(), "imprecise card mark used with array"); + } + } + @Snippet public static void g1ArrayRangePreWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); @@ -415,11 +432,13 @@ private final CompressEncoding oopEncoding; private final Counters counters; + private final boolean verifyBarrier; - public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, - CompressEncoding oopEncoding) { + public Templates(OptionValues options, Iterable factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target, + GraalHotSpotVMConfig config) { super(options, factories, providers, providers.getSnippetReflection(), target); - this.oopEncoding = oopEncoding; + this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null; + this.verifyBarrier = ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC; this.counters = new Counters(factory); } @@ -432,6 +451,7 @@ args = new Arguments(serialImpreciseWriteBarrier, writeBarrier.graph().getGuardsStage(), tool.getLoweringStage()); OffsetAddressNode address = (OffsetAddressNode) writeBarrier.getAddress(); args.add("object", address.getBase()); + args.addConst("verifyBarrier", verifyBarrier); } args.addConst("counters", counters); template(writeBarrier, args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); @@ -519,6 +539,7 @@ args.add("value", value); args.addConst("usePrecise", writeBarrierPost.usePrecise()); + args.addConst("verifyBarrier", verifyBarrier); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("trace", traceBarrier(writeBarrierPost.graph())); args.addConst("counters", counters); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DivisionByZeroExceptionStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DivisionByZeroExceptionStub.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.stubs; + +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.nodes.CStringConstant; +import org.graalvm.compiler.word.Word; + +import jdk.vm.ci.code.Register; + +/** + * Stub to allocate an {@link ArithmeticException} thrown by a bytecode for a division by zero. + */ +public class DivisionByZeroExceptionStub extends CreateExceptionStub { + public DivisionByZeroExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createDivisionByZeroException", options, providers, linkage); + } + + @Override + protected Object getConstantParameterValue(int index, String name) { + GraalError.guarantee(index == 0, "unknown parameter %s at index %d", name, index); + return providers.getRegisters().getThreadRegister(); + } + + @Snippet + private static Object createDivisionByZeroException(@ConstantParameter Register threadRegister) { + Word msg = CStringConstant.cstring("/ by zero"); + return createException(threadRegister, ArithmeticException.class, msg); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static org.graalvm.compiler.hotspot.stubs.StubUtil.printNumber; +import static org.graalvm.compiler.hotspot.stubs.StubUtil.printString; + import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.debug.GraalError; @@ -29,6 +32,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.AllocaNode; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -37,51 +41,52 @@ * Stub to allocate an {@link ArrayIndexOutOfBoundsException} thrown by a bytecode. */ public class OutOfBoundsExceptionStub extends CreateExceptionStub { - public OutOfBoundsExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { super("createOutOfBoundsException", options, providers, linkage); } + // JDK-8201593: Print array length in ArrayIndexOutOfBoundsException. + private static final boolean PRINT_LENGTH_IN_EXCEPTION = GraalServices.JAVA_SPECIFICATION_VERSION >= 11; private static final int MAX_INT_STRING_SIZE = Integer.toString(Integer.MIN_VALUE).length(); + private static final String STR_INDEX = "Index "; + private static final String STR_OUTOFBOUNDSFORLENGTH = " out of bounds for length "; @Override protected Object getConstantParameterValue(int index, String name) { switch (index) { - case 1: + case 2: return providers.getRegisters().getThreadRegister(); - case 2: + case 3: int wordSize = providers.getWordTypes().getWordKind().getByteCount(); - // (MAX_INT_STRING_SIZE + 1) / wordSize, rounded up - return MAX_INT_STRING_SIZE / wordSize + 1; + int bytes; + if (PRINT_LENGTH_IN_EXCEPTION) { + bytes = STR_INDEX.length() + STR_OUTOFBOUNDSFORLENGTH.length() + 2 * MAX_INT_STRING_SIZE; + } else { + bytes = MAX_INT_STRING_SIZE; + } + // (required words for maximum length + nullbyte), rounded up + return (bytes + 1) / wordSize + 1; + case 4: + return PRINT_LENGTH_IN_EXCEPTION; default: throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); } } @Snippet - private static Object createOutOfBoundsException(int idx, @ConstantParameter Register threadRegister, @ConstantParameter int bufferSizeInWords) { + private static Object createOutOfBoundsException(int idx, int length, @ConstantParameter Register threadRegister, @ConstantParameter int bufferSizeInWords, + @ConstantParameter boolean printLengthInException) { Word buffer = AllocaNode.alloca(bufferSizeInWords); - - long number = idx; - if (number < 0) { - number = -number; + Word ptr; + if (printLengthInException) { + ptr = printString(buffer, STR_INDEX); + ptr = printNumber(ptr, idx); + ptr = printString(ptr, STR_OUTOFBOUNDSFORLENGTH); + ptr = printNumber(ptr, length); + } else { + ptr = printNumber(buffer, idx); } - - Word ptr = buffer.add(MAX_INT_STRING_SIZE); ptr.writeByte(0, (byte) 0); - do { - long digit = number % 10; - number /= 10; - - ptr = ptr.subtract(1); - ptr.writeByte(0, (byte) ('0' + digit)); - } while (number > 0); - - if (idx < 0) { - ptr = ptr.subtract(1); - ptr.writeByte(0, (byte) '-'); - } - - return createException(threadRegister, ArrayIndexOutOfBoundsException.class, ptr); + return createException(threadRegister, ArrayIndexOutOfBoundsException.class, buffer); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ package org.graalvm.compiler.hotspot.stubs; import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic; @@ -272,4 +272,59 @@ static int hubOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.hubOffset; } + + /** + * Print {@code number} as decimal string to {@code buffer}. + * + * @param buffer + * @param number + * @return A pointer pointing one byte right after the last printed digit in {@code buffer}. + */ + public static Word printNumber(Word buffer, long number) { + long tmpNumber = number; + int offset; + if (tmpNumber <= 0) { + tmpNumber = -tmpNumber; + offset = 1; + } else { + offset = 0; + } + while (tmpNumber > 0) { + tmpNumber /= 10; + offset++; + } + tmpNumber = number < 0 ? -number : number; + Word ptr = buffer.add(offset); + do { + long digit = tmpNumber % 10; + tmpNumber /= 10; + ptr = ptr.subtract(1); + ptr.writeByte(0, (byte) ('0' + digit)); + } while (tmpNumber > 0); + + if (number < 0) { + ptr = ptr.subtract(1); + ptr.writeByte(0, (byte) '-'); + } + return buffer.add(offset); + } + + /** + * Copy {@code javaString} bytes to the memory location {@code ptr}. + * + * @param buffer + * @param javaString + * @return A pointer pointing one byte right after the last byte copied from {@code javaString} + * to {@code ptr} + */ + public static Word printString(Word buffer, String javaString) { + Word string = cstring(javaString); + int i = 0; + byte b; + while ((b = string.readByte(i)) != 0) { + buffer.writeByte(i, b); + i++; + } + return buffer.add(i); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Thu May 31 13:39:26 2018 -0700 @@ -31,6 +31,7 @@ import static org.graalvm.compiler.bytecode.Bytecodes.BASTORE; import static org.graalvm.compiler.bytecode.Bytecodes.CALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.CASTORE; +import static org.graalvm.compiler.bytecode.Bytecodes.CHECKCAST; import static org.graalvm.compiler.bytecode.Bytecodes.DALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.DASTORE; import static org.graalvm.compiler.bytecode.Bytecodes.DRETURN; @@ -43,6 +44,7 @@ import static org.graalvm.compiler.bytecode.Bytecodes.GOTO_W; import static org.graalvm.compiler.bytecode.Bytecodes.IALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.IASTORE; +import static org.graalvm.compiler.bytecode.Bytecodes.IDIV; import static org.graalvm.compiler.bytecode.Bytecodes.IFEQ; import static org.graalvm.compiler.bytecode.Bytecodes.IFGE; import static org.graalvm.compiler.bytecode.Bytecodes.IFGT; @@ -64,12 +66,15 @@ import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESPECIAL; import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESTATIC; import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; +import static org.graalvm.compiler.bytecode.Bytecodes.IREM; import static org.graalvm.compiler.bytecode.Bytecodes.IRETURN; import static org.graalvm.compiler.bytecode.Bytecodes.JSR; import static org.graalvm.compiler.bytecode.Bytecodes.JSR_W; import static org.graalvm.compiler.bytecode.Bytecodes.LALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.LASTORE; +import static org.graalvm.compiler.bytecode.Bytecodes.LDIV; import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH; +import static org.graalvm.compiler.bytecode.Bytecodes.LREM; import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN; import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD; import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC; @@ -650,6 +655,10 @@ } break; } + case IDIV: + case IREM: + case LDIV: + case LREM: case IASTORE: case LASTORE: case FASTORE: @@ -667,6 +676,7 @@ case CALOAD: case SALOAD: case ARRAYLENGTH: + case CHECKCAST: case PUTSTATIC: case GETSTATIC: case PUTFIELD: diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -377,7 +377,10 @@ import org.graalvm.compiler.nodes.extended.AnchoringNode; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; +import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.extended.MembarNode; @@ -398,6 +401,7 @@ import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode; +import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; @@ -423,6 +427,7 @@ import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.DeoptimizationAction; @@ -1133,12 +1138,12 @@ finishedDispatch.setNext(target); } - protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, JavaKind kind) { - return LoadIndexedNode.create(graph.getAssumptions(), array, index, kind, metaAccess, constantReflection); - } - - protected void genStoreIndexed(ValueNode array, ValueNode index, JavaKind kind, ValueNode value) { - add(new StoreIndexedNode(array, index, kind, value)); + protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind kind) { + return LoadIndexedNode.create(graph.getAssumptions(), array, index, boundsCheck, kind, metaAccess, constantReflection); + } + + protected void genStoreIndexed(ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind kind, ValueNode value) { + add(new StoreIndexedNode(array, index, boundsCheck, storeCheck, kind, value)); } protected ValueNode genIntegerAdd(ValueNode x, ValueNode y) { @@ -1173,12 +1178,12 @@ return RemNode.create(x, y, NodeView.DEFAULT); } - protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) { - return SignedDivNode.create(x, y, NodeView.DEFAULT); - } - - protected ValueNode genIntegerRem(ValueNode x, ValueNode y) { - return SignedRemNode.create(x, y, NodeView.DEFAULT); + protected ValueNode genIntegerDiv(ValueNode x, ValueNode y, GuardingNode zeroCheck) { + return SignedDivNode.create(x, y, zeroCheck, NodeView.DEFAULT); + } + + protected ValueNode genIntegerRem(ValueNode x, ValueNode y, GuardingNode zeroCheck) { + return SignedRemNode.create(x, y, zeroCheck, NodeView.DEFAULT); } protected ValueNode genNegateOp(ValueNode x) { @@ -1267,10 +1272,12 @@ protected void genThrow() { genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); - ValueNode exception = frameState.pop(JavaKind.Object); - FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); - ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp(NodeView.DEFAULT).join(objectNonNull()), nullCheck)); - lastInstr.setNext(handleException(nonNullException, bci(), false)); + ValueNode exception = maybeEmitExplicitNullCheck(frameState.pop(JavaKind.Object)); + if (!StampTool.isPointerNonNull(exception.stamp(NodeView.DEFAULT))) { + FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); + exception = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp(NodeView.DEFAULT).join(objectNonNull()), nullCheck)); + } + lastInstr.setNext(handleException(exception, bci(), false)); } protected LogicNode createInstanceOf(TypeReference type, ValueNode object) { @@ -1324,30 +1331,61 @@ return new StateSplitProxyNode(fieldRead); } - protected ValueNode emitExplicitNullCheck(ValueNode receiver) { - if (StampTool.isPointerNonNull(receiver.stamp(NodeView.DEFAULT))) { + protected ValueNode maybeEmitExplicitNullCheck(ValueNode receiver) { + if (StampTool.isPointerNonNull(receiver.stamp(NodeView.DEFAULT)) || !needsExplicitNullCheckException(receiver)) { return receiver; } - BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); - AbstractBeginNode falseSucc = graph.add(new BeginNode()); - ValueNode nonNullReceiver = graph.addOrUniqueWithInputs(PiNode.create(receiver, objectNonNull(), falseSucc)); - append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY)); - lastInstr = falseSucc; + LogicNode condition = genUnique(IsNullNode.create(receiver)); + AbstractBeginNode passingSuccessor = emitBytecodeExceptionCheck(condition, false, BytecodeExceptionKind.NULL_POINTER); + return genUnique(PiNode.create(receiver, objectNonNull(), passingSuccessor)); + } + + protected GuardingNode maybeEmitExplicitBoundsCheck(ValueNode receiver, ValueNode index) { + if (!needsExplicitBoundsCheckException(receiver, index)) { + return null; + } + ValueNode length = append(genArrayLength(receiver)); + LogicNode condition = genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length, NodeView.DEFAULT)); + return emitBytecodeExceptionCheck(condition, true, BytecodeExceptionKind.OUT_OF_BOUNDS, index, length); + } + + protected GuardingNode maybeEmitExplicitStoreCheck(ValueNode array, JavaKind elementKind, ValueNode value) { + if (elementKind != JavaKind.Object || StampTool.isPointerAlwaysNull(value) || !needsExplicitStoreCheckException(array, value)) { + return null; + } + ValueNode arrayClass = genUnique(LoadHubNode.create(array, stampProvider, metaAccess, constantReflection)); + ValueNode componentHub = append(LoadArrayComponentHubNode.create(arrayClass, stampProvider, metaAccess, constantReflection)); + LogicNode condition = genUnique(InstanceOfDynamicNode.create(graph.getAssumptions(), getConstantReflection(), componentHub, value, true)); + return emitBytecodeExceptionCheck(condition, true, BytecodeExceptionKind.ARRAY_STORE, value); + } + + protected GuardingNode maybeEmitExplicitDivisionByZeroCheck(ValueNode y) { + if (!((IntegerStamp) y.stamp(NodeView.DEFAULT)).contains(0) || !needsExplicitDivisionByZeroException(y)) { + return null; + } + ConstantNode zero = ConstantNode.defaultForKind(y.getStackKind(), graph); + LogicNode condition = genUnique(IntegerEqualsNode.create(constantReflection, metaAccess, options, null, y, zero, NodeView.DEFAULT)); + return emitBytecodeExceptionCheck(condition, false, BytecodeExceptionKind.DIVISION_BY_ZERO); + } + + private AbstractBeginNode emitBytecodeExceptionCheck(LogicNode condition, boolean passingOnTrue, BytecodeExceptionKind exceptionKind, ValueNode... arguments) { + if (passingOnTrue ? condition.isTautology() : condition.isContradiction()) { + return null; + } + + BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, exceptionKind, arguments)); + AbstractBeginNode passingSuccessor = graph.add(new BeginNode()); + + FixedNode trueSuccessor = passingOnTrue ? passingSuccessor : exception; + FixedNode falseSuccessor = passingOnTrue ? exception : passingSuccessor; + append(new IfNode(condition, trueSuccessor, falseSuccessor, SLOW_PATH_PROBABILITY)); + lastInstr = passingSuccessor; exception.setStateAfter(createFrameState(bci(), exception)); exception.setNext(handleException(exception, bci(), false)); EXPLICIT_EXCEPTIONS.increment(debug); - return nonNullReceiver; - } - - protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { - AbstractBeginNode trueSucc = graph.add(new BeginNode()); - BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); - append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length, NodeView.DEFAULT)), trueSucc, exception, FAST_PATH_PROBABILITY)); - lastInstr = trueSucc; - - exception.setStateAfter(createFrameState(bci(), exception)); - exception.setNext(handleException(exception, bci(), false)); + + return passingSuccessor; } protected ValueNode genArrayLength(ValueNode x) { @@ -1617,7 +1655,7 @@ returnType = returnType.resolve(targetMethod.getDeclaringClass()); } if (invokeKind.hasReceiver()) { - args[0] = emitExplicitExceptions(args[0]); + args[0] = maybeEmitExplicitNullCheck(args[0]); } if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) { @@ -1910,8 +1948,8 @@ /** * Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod} - * and not another method that overrides it. This should only be called if there is an intrinsic - * (i.e., an {@link InvocationPlugin}) for {@code targetMethod} and the invocation is indirect. + * and not another method that overrides it. This should only be called if there is an + * {@link InvocationPlugin} for {@code targetMethod} and the invocation is indirect. * * The control flow woven around the intrinsic is as follows: * @@ -2066,9 +2104,7 @@ if (plugin != null) { if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) { - // Self recursive intrinsic means the original - // method should be called. - assert !targetMethod.hasBytecodes() : "TODO: when does this happen?"; + // Self recursive intrinsic means the original method should be called. return false; } @@ -2088,7 +2124,7 @@ try (DebugCloseable context = openNodeContext(targetMethod)) { if (plugin.execute(this, targetMethod, pluginReceiver, args)) { afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType); - return true; + return !plugin.isDecorator(); } else { afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType); } @@ -2911,75 +2947,87 @@ } } + @SuppressWarnings("try") private void createUnwind() { assert frameState.stackSize() == 1 : frameState; synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null); - ValueNode exception = frameState.pop(JavaKind.Object); - append(new UnwindNode(exception)); - } - + try (DebugCloseable context = openNodeContext(frameState, BytecodeFrame.UNWIND_BCI)) { + ValueNode exception = frameState.pop(JavaKind.Object); + append(new UnwindNode(exception)); + } + } + + @SuppressWarnings("try") private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) { - if (method.isSynchronized()) { - if (currentReturnValue != null) { - frameState.push(currentReturnValueKind, currentReturnValue); + try (DebugCloseable context = openNodeContext(frameState, bci)) { + if (method.isSynchronized()) { + if (currentReturnValue != null) { + frameState.push(currentReturnValueKind, currentReturnValue); + } + genMonitorExit(methodSynchronizedObject, currentReturnValue, bci); + assert !frameState.rethrowException(); + finishPrepare(lastInstr, bci); } - genMonitorExit(methodSynchronizedObject, currentReturnValue, bci); - assert !frameState.rethrowException(); - finishPrepare(lastInstr, bci); - } - if (frameState.lockDepth(false) != 0) { - throw bailout("unbalanced monitors: too few exits exiting frame"); - } - } - + if (frameState.lockDepth(false) != 0) { + throw bailout("unbalanced monitors: too few exits exiting frame"); + } + } + } + + @SuppressWarnings("try") private void createExceptionDispatch(ExceptionDispatchBlock block) { - lastInstr = finishInstruction(lastInstr, frameState); - - assert frameState.stackSize() == 1 : frameState; - if (block.handler.isCatchAll()) { - assert block.getSuccessorCount() == 1; - appendGoto(block.getSuccessor(0)); - return; - } - - JavaType catchType = block.handler.getCatchType(); - if (graphBuilderConfig.eagerResolving()) { - catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF); - } - if (catchType instanceof ResolvedJavaType) { - TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType); - - if (graphBuilderConfig.getSkippedExceptionTypes() != null) { - for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { - if (skippedType.isAssignableFrom(checkedCatchType.getType())) { - BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1); - ValueNode exception = frameState.stack[0]; - FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); - FixedNode nextDispatch = createTarget(nextBlock, frameState); - append(new IfNode(graph.addOrUniqueWithInputs(createInstanceOf(checkedCatchType, exception)), trueSuccessor, nextDispatch, 0)); - return; + try (DebugCloseable context = openNodeContext(frameState, BytecodeFrame.AFTER_EXCEPTION_BCI)) { + lastInstr = finishInstruction(lastInstr, frameState); + + assert frameState.stackSize() == 1 : frameState; + if (block.handler.isCatchAll()) { + assert block.getSuccessorCount() == 1; + appendGoto(block.getSuccessor(0)); + return; + } + + JavaType catchType = block.handler.getCatchType(); + if (graphBuilderConfig.eagerResolving()) { + catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF); + } + if (catchType instanceof ResolvedJavaType) { + TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType); + + if (graphBuilderConfig.getSkippedExceptionTypes() != null) { + for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { + if (skippedType.isAssignableFrom(checkedCatchType.getType())) { + BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1); + ValueNode exception = frameState.stack[0]; + FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); + FixedNode nextDispatch = createTarget(nextBlock, frameState); + append(new IfNode(graph.addOrUniqueWithInputs(createInstanceOf(checkedCatchType, exception)), trueSuccessor, nextDispatch, 0)); + return; + } } } + + BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1); + ValueNode exception = frameState.stack[0]; + /* + * Anchor for the piNode, which must be before any LoopExit inserted by + * createTarget. + */ + BeginNode piNodeAnchor = graph.add(new BeginNode()); + ObjectStamp checkedStamp = StampFactory.objectNonNull(checkedCatchType); + PiNode piNode = graph.addWithoutUnique(new PiNode(exception, checkedStamp)); + frameState.pop(JavaKind.Object); + frameState.push(JavaKind.Object, piNode); + FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState); + frameState.pop(JavaKind.Object); + frameState.push(JavaKind.Object, exception); + FixedNode nextDispatch = createTarget(nextBlock, frameState); + piNodeAnchor.setNext(catchSuccessor); + IfNode ifNode = append(new IfNode(graph.unique(createInstanceOf(checkedCatchType, exception)), piNodeAnchor, nextDispatch, 0.5)); + assert ifNode.trueSuccessor() == piNodeAnchor; + piNode.setGuard(ifNode.trueSuccessor()); + } else { + handleUnresolvedExceptionType(catchType); } - - BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1); - ValueNode exception = frameState.stack[0]; - /* Anchor for the piNode, which must be before any LoopExit inserted by createTarget. */ - BeginNode piNodeAnchor = graph.add(new BeginNode()); - ObjectStamp checkedStamp = StampFactory.objectNonNull(checkedCatchType); - PiNode piNode = graph.addWithoutUnique(new PiNode(exception, checkedStamp)); - frameState.pop(JavaKind.Object); - frameState.push(JavaKind.Object, piNode); - FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState); - frameState.pop(JavaKind.Object); - frameState.push(JavaKind.Object, exception); - FixedNode nextDispatch = createTarget(nextBlock, frameState); - piNodeAnchor.setNext(catchSuccessor); - IfNode ifNode = append(new IfNode(graph.unique(createInstanceOf(checkedCatchType, exception)), piNodeAnchor, nextDispatch, 0.5)); - assert ifNode.trueSuccessor() == piNodeAnchor; - piNode.setGuard(ifNode.trueSuccessor()); - } else { - handleUnresolvedExceptionType(catchType); } } @@ -3220,22 +3268,22 @@ } protected double getProfileProbability(boolean negate) { - double probability; if (profilingInfo == null) { - probability = 0.5; - } else { - assert assertAtIfBytecode(); - probability = profilingInfo.getBranchTakenProbability(bci()); - if (probability < 0) { - assert probability == -1 : "invalid probability"; - debug.log("missing probability in %s at bci %d", code, bci()); - probability = 0.5; - } else { - if (negate) { - // the probability coming from profile is about the original condition - probability = 1 - probability; - } - } + return 0.5; + } + + assert assertAtIfBytecode(); + double probability = profilingInfo.getBranchTakenProbability(bci()); + + if (probability < 0) { + assert probability == -1 : "invalid probability"; + debug.log("missing probability in %s at bci %d", code, bci()); + return 0.5; + } + + if (negate && shouldComplementProbability()) { + // the probability coming from profile is about the original condition + probability = 1 - probability; } return probability; } @@ -3277,7 +3325,10 @@ BciBlock tmpBlock = trueBlock; trueBlock = falseBlock; falseBlock = tmpBlock; - probability = 1 - probability; + if (shouldComplementProbability()) { + // the probability coming from profile is about the original condition + probability = 1 - probability; + } condition = logicNegationNode.getValue(); } @@ -3288,9 +3339,13 @@ condition = genUnique(condition); } + NodeSourcePosition currentPosition = graph.currentNodeSourcePosition(); if (isNeverExecutedCode(probability)) { if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != trueBlock.startBci) { - append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true)); + NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition() + ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), falseBlock.startBci) + : null; + append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true, survivingSuccessorPosition)); if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore); } @@ -3299,7 +3354,10 @@ } } else if (isNeverExecutedCode(1 - probability)) { if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != falseBlock.startBci) { - append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false)); + NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition() + ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), trueBlock.startBci) + : null; + append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false, survivingSuccessorPosition)); if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore); } @@ -3333,6 +3391,14 @@ } /** + * Hook for subclasses to decide whether the IfNode probability should be complemented during + * conversion to Graal IR. + */ + protected boolean shouldComplementProbability() { + return true; + } + + /** * Hook for subclasses to generate custom nodes before an IfNode. */ @SuppressWarnings("unused") @@ -3587,29 +3653,36 @@ private void genLoadIndexed(JavaKind kind) { ValueNode index = frameState.pop(JavaKind.Int); - ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), index); + ValueNode array = frameState.pop(JavaKind.Object); + + array = maybeEmitExplicitNullCheck(array); + GuardingNode boundsCheck = maybeEmitExplicitBoundsCheck(array, index); for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { - if (plugin.handleLoadIndexed(this, array, index, kind)) { + if (plugin.handleLoadIndexed(this, array, index, boundsCheck, kind)) { return; } } - frameState.push(kind, append(genLoadIndexed(array, index, kind))); + frameState.push(kind, append(genLoadIndexed(array, index, boundsCheck, kind))); } private void genStoreIndexed(JavaKind kind) { ValueNode value = frameState.pop(kind); ValueNode index = frameState.pop(JavaKind.Int); - ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), index); + ValueNode array = frameState.pop(JavaKind.Object); + + array = maybeEmitExplicitNullCheck(array); + GuardingNode boundsCheck = maybeEmitExplicitBoundsCheck(array, index); + GuardingNode storeCheck = maybeEmitExplicitStoreCheck(array, kind, value); for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { - if (plugin.handleStoreIndexed(this, array, index, kind, value)) { + if (plugin.handleStoreIndexed(this, array, index, boundsCheck, storeCheck, kind, value)) { return; } } - genStoreIndexed(array, index, kind, value); + genStoreIndexed(array, index, boundsCheck, storeCheck, kind, value); } private void genArithmeticOp(JavaKind kind, int opcode) { @@ -3658,15 +3731,18 @@ private void genIntegerDivOp(JavaKind kind, int opcode) { ValueNode y = frameState.pop(kind); ValueNode x = frameState.pop(kind); + + GuardingNode zeroCheck = maybeEmitExplicitDivisionByZeroCheck(y); + ValueNode v; switch (opcode) { case IDIV: case LDIV: - v = genIntegerDiv(x, y); + v = genIntegerDiv(x, y, zeroCheck); break; case IREM: case LREM: - v = genIntegerRem(x, y); + v = genIntegerRem(x, y, zeroCheck); break; default: throw shouldNotReachHere(); @@ -3871,7 +3947,8 @@ handleUnresolvedCheckCast(type, object); return; } - TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type); + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), resolvedType); JavaTypeProfile profile = getProfileForTypeCheck(checkedType); for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { @@ -3903,8 +3980,16 @@ if (condition.isTautology()) { castNode = object; } else { - FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), fixedGuard)); + GuardingNode guard; + if (needsExplicitClassCastException(object)) { + Constant hub = getConstantReflection().asObjectHub(resolvedType); + Stamp hubStamp = getStampProvider().createHubStamp(StampFactory.object(TypeReference.createExactTrusted(resolvedType))); + ConstantNode hubConstant = ConstantNode.forConstant(hubStamp, hub, getMetaAccess(), graph); + guard = emitBytecodeExceptionCheck(condition, true, BytecodeExceptionKind.CLASS_CAST, object, hubConstant); + } else { + guard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); + } + castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), guard.asNode())); } } frameState.push(JavaKind.Object, castNode); @@ -4124,7 +4209,7 @@ } private void genGetField(JavaField field, ValueNode receiverInput) { - ValueNode receiver = emitExplicitExceptions(receiverInput); + ValueNode receiver = maybeEmitExplicitNullCheck(receiverInput); if (field instanceof ResolvedJavaField) { ResolvedJavaField resolvedField = (ResolvedJavaField) field; genGetField(resolvedField, receiver); @@ -4163,29 +4248,56 @@ } /** - * @param receiver the receiver of an object based operation - * @param index the index of an array based operation that is to be tested for out of bounds. - * This is null for a non-array operation. - * @return the receiver value possibly modified to have a non-null stamp + * Returns true if an explicit null check should be emitted for the given object. + * + * @param object The object that is accessed. + */ + protected boolean needsExplicitNullCheckException(ValueNode object) { + return needsExplicitException(); + } + + /** + * Returns true if an explicit null check should be emitted for the given object. + * + * @param array The array that is accessed. + * @param index The array index that is accessed. + */ + protected boolean needsExplicitBoundsCheckException(ValueNode array, ValueNode index) { + return needsExplicitException(); + } + + /** + * Returns true if an explicit check for a {@link ClassCastException} should be emitted for the + * given object. + * + * @param object The object that is accessed. */ - protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) { - if (needsExplicitException()) { - ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); - ValueNode length = append(genArrayLength(nonNullReceiver)); - emitExplicitBoundsCheck(index, length); - return nonNullReceiver; - } - return receiver; - } - - protected ValueNode emitExplicitExceptions(ValueNode receiver) { - if (StampTool.isPointerNonNull(receiver) || !needsExplicitException()) { - return receiver; - } else { - return emitExplicitNullCheck(receiver); - } - } - + protected boolean needsExplicitClassCastException(ValueNode object) { + return needsExplicitException(); + } + + /** + * Returns true if an explicit null check should be emitted for the given object. + * + * @param array The array that is accessed. + * @param value The value that is stored into the array. + */ + protected boolean needsExplicitStoreCheckException(ValueNode array, ValueNode value) { + return needsExplicitException(); + } + + /** + * Returns true if an explicit null check should be emitted for the given object. + * + * @param y The dividend. + */ + protected boolean needsExplicitDivisionByZeroException(ValueNode y) { + return needsExplicitException(); + } + + /** + * Returns true if an explicit exception check should be emitted. + */ protected boolean needsExplicitException() { BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode(); if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) { @@ -4206,7 +4318,8 @@ } private void genPutField(JavaField field, ValueNode value) { - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object)); + ValueNode receiver = maybeEmitExplicitNullCheck(frameState.pop(JavaKind.Object)); + if (field instanceof ResolvedJavaField) { ResolvedJavaField resolvedField = (ResolvedJavaField) field; @@ -4703,7 +4816,7 @@ } private void genArrayLength() { - ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object)); + ValueNode array = maybeEmitExplicitNullCheck(frameState.pop(JavaKind.Object)); frameState.push(JavaKind.Int, append(genArrayLength(array))); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAllocateInstance01.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAllocateInstance01.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAllocateInstance01.java Thu May 31 13:39:26 2018 -0700 @@ -67,6 +67,7 @@ runTest("testInstance"); } + @Ignore("https://bugs.openjdk.java.net/browse/JDK-8153540") @Test public void run1() throws Throwable { runTest("testClassForException", UnsafeAllocateInstance01[].class); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/CE_InstanceOf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/CE_InstanceOf.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; + +public class CE_InstanceOf extends JTTTest { + + static class A { + } + + static class B extends A { + } + + static class C extends A { + } + + public static A testRedundantCast(Object value) { + if (value != null && value.getClass() == A.class) { + return (A) value; + } + return null; + } + + public static boolean testRedundantInstanceOf(Object value) { + if (value != null && value.getClass() == A.class) { + return (value instanceof A); + } + return false; + } + + public static boolean testRedundantInstanceOf2(Object value) { + if (value.getClass() == A.class) { + return (value instanceof A); + } + return false; + } + + public static boolean testNonRedundantInstanceOf(Object value) { + if (value instanceof A) { + return (value != null && value.getClass() == A.class); + } + return false; + } + + public static Object testNonRedundantInstanceOf2(Object value) { + if (value != null && value.getClass() == Object[].class) { + return ((Object[]) value)[0]; + } + return null; + } + + private static final List testArgs = Collections.unmodifiableList(Arrays.asList(new A(), new B(), null)); + + @Test + public void run0() throws Throwable { + for (A a : testArgs) { + runTest("testRedundantCast", a); + } + } + + @Test + public void run1() throws Throwable { + for (A a : testArgs) { + runTest("testRedundantInstanceOf", a); + } + } + + @Test + public void run2() throws Throwable { + for (A a : testArgs) { + runTest("testRedundantInstanceOf2", a); + } + } + + @Test + public void run3() throws Throwable { + for (A a : testArgs) { + runTest("testNonRedundantInstanceOf", a); + } + } + + @Test + public void run4() throws Throwable { + for (A a : testArgs) { + runTest("testNonRedundantInstanceOf2", a); + } + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/InstanceOf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/InstanceOf.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.java.InstanceOfNode; +import org.junit.Test; + +/** + * A few tests of expected simplifications by {@link InstanceOfNode#implies(boolean, LogicNode)}. + */ +public class InstanceOf extends JTTTest { + + static class A { + } + + static class B extends A { + } + + static class C extends B { + } + + public boolean testSnippet1(Object o) { + if (o instanceof B) { + if (o instanceof A) { + return true; + } + } + return false; + } + + public boolean testSnippet2(Object o) { + if (o instanceof A) { + return true; + } else { + return o instanceof B; + } + } + + @Test + public void test1() { + runTest("testSnippet1", new A()); + runTest("testSnippet1", new B()); + runTest("testSnippet1", new C()); + } + + @Test + public void test2() { + runTest("testSnippet2", new A()); + runTest("testSnippet2", new B()); + runTest("testSnippet2", new C()); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticLIRGeneratorTool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticLIRGeneratorTool.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticLIRGeneratorTool.java Thu May 31 13:39:26 2018 -0700 @@ -37,5 +37,20 @@ Value emitCountTrailingZeros(Value value); + enum RoundingMode { + NEAREST(0), + DOWN(1), + UP(2), + TRUNCATE(3); + + public final int encoding; + + RoundingMode(int encoding) { + this.encoding = encoding; + } + } + + Value emitRound(Value value, RoundingMode mode); + void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java Thu May 31 13:39:26 2018 -0700 @@ -74,6 +74,9 @@ FREM, FNEG, FABS, + FRINTM, + FRINTN, + FRINTP, SQRT; /** @@ -133,6 +136,15 @@ case FABS: masm.fabs(size, dst, src); break; + case FRINTM: + masm.frintm(size, dst, src); + break; + case FRINTN: + masm.frintn(size, dst, src); + break; + case FRINTP: + masm.frintp(size, dst, src); + break; case SQRT: masm.fsqrt(size, dst, src); break; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java Thu May 31 13:39:26 2018 -0700 @@ -26,13 +26,12 @@ import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ShiftType; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import jdk.vm.ci.aarch64.AArch64.CPUFeature; -import jdk.vm.ci.aarch64.AArch64.Flag; import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -76,15 +75,15 @@ Register address = asRegister(addressValue); Register result = asRegister(resultValue); Register newVal = asRegister(newValue); - if (masm.supports(CPUFeature.LSE) || masm.isFlagSet(Flag.UseLSE)) { + if (AArch64LIRFlagsVersioned.useLSE(masm)) { Register expected = asRegister(expectedValue); masm.mov(size, result, expected); - masm.cas(size, expected, newVal, address, true /*acquire*/, true /*release*/); + masm.cas(size, expected, newVal, address, true /* acquire */, true /* release */); AArch64Compare.gpCompare(masm, resultValue, expectedValue); } else { - // We could avoid using a scratch register here, by reusing resultValue for the stlxr - // success flag and issue a mov resultValue, expectedValue in case of success before - // returning. + // We could avoid using a scratch register here, by reusing resultValue for the + // stlxr success flag and issue a mov resultValue, expectedValue in case of success + // before returning. Register scratch = asRegister(scratchValue); Label retry = new Label(); Label fail = new Label(); @@ -99,4 +98,59 @@ } } } + + /** + * Load (Read) and Add instruction. Does the following atomically: + * ATOMIC_READ_AND_ADD(addend, result, address): + * result = *address + * *address = result + addend + * return result + * + */ + @Opcode("ATOMIC_READ_AND_ADD") + public static final class AtomicReadAndAddOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AtomicReadAndAddOp.class); + + private final AArch64Kind accessKind; + + @Def protected AllocatableValue resultValue; + @Alive protected AllocatableValue addressValue; + @Alive protected Value deltaValue; + @Temp protected AllocatableValue scratchValue1; + @Temp protected AllocatableValue scratchValue2; + + public AtomicReadAndAddOp(AArch64Kind kind, AllocatableValue result, AllocatableValue address, Value delta, AllocatableValue scratch1, AllocatableValue scratch2) { + super(TYPE); + this.accessKind = kind; + this.resultValue = result; + this.addressValue = address; + this.deltaValue = delta; + this.scratchValue1 = scratch1; + this.scratchValue2 = scratch2; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + assert accessKind.isInteger(); + final int size = accessKind.getSizeInBytes() * Byte.SIZE; + + Register address = asRegister(addressValue); + Register delta = asRegister(deltaValue); + Register result = asRegister(resultValue); + + if (AArch64LIRFlagsVersioned.useLSE(masm)) { + masm.ldadd(size, delta, result, address, true, true); + } else { + Register scratch1 = asRegister(scratchValue1); + Register scratch2 = asRegister(scratchValue2); + Label retry = new Label(); + masm.bind(retry); + masm.ldaxr(size, result, address); + masm.add(size, scratch1, result, delta, ShiftType.LSL, 0); + masm.stlxr(size, scratch2, scratch1, address); + // if scratch2 == 0 then write successful, else retry + masm.cbnz(32, scratch2, retry); + } + } + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +23,7 @@ */ package org.graalvm.compiler.lir.aarch64; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; @@ -198,12 +200,16 @@ public static void directCall(CompilationResultBuilder crb, AArch64MacroAssembler masm, InvokeTarget callTarget, Register scratch, LIRFrameState info, Label label) { int before = masm.position(); if (scratch != null) { - /* - * Offset might not fit into a 28-bit immediate, generate an indirect call with a 64-bit - * immediate address which is fixed up by HotSpot. - */ - masm.movNativeAddress(scratch, 0L); - masm.blr(scratch); + if (GeneratePIC.getValue(crb.getOptions())) { + masm.bl(0); + } else { + /* + * Offset might not fit into a 28-bit immediate, generate an indirect call with a + * 64-bit immediate address which is fixed up by HotSpot. + */ + masm.movNativeAddress(scratch, 0L); + masm.blr(scratch); + } } else { // Address is fixed up by HotSpot. masm.bl(0); @@ -230,8 +236,12 @@ public static void directJmp(CompilationResultBuilder crb, AArch64MacroAssembler masm, InvokeTarget callTarget) { try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) { int before = masm.position(); - masm.movNativeAddress(scratch.getRegister(), 0L); - masm.jmp(scratch.getRegister()); + if (GeneratePIC.getValue(crb.getOptions())) { + masm.jmp(); + } else { + masm.movNativeAddress(scratch.getRegister(), 0L); + masm.jmp(scratch.getRegister()); + } int after = masm.position(); crb.recordDirectCall(before, after, callTarget, null); masm.ensureUniquePC(); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64LIRFlagsVersioned.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64LIRFlagsVersioned.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; + +import jdk.vm.ci.aarch64.AArch64.CPUFeature; +import jdk.vm.ci.aarch64.AArch64.Flag; + +public class AArch64LIRFlagsVersioned { + public static boolean useLSE(AArch64MacroAssembler masm) { + return masm.supports(CPUFeature.LSE) || masm.isFlagSet(Flag.UseLSE); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Thu May 31 13:39:26 2018 -0700 @@ -162,7 +162,12 @@ @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); - masm.loadAddress(dst, (AArch64Address) crb.recordDataReferenceInCode(data), data.getAlignment()); + if (crb.compilationResult.isImmutablePIC()) { + crb.recordDataReferenceInCode(data); + masm.addressOf(dst); + } else { + masm.loadAddress(dst, (AArch64Address) crb.recordDataReferenceInCode(data), data.getAlignment()); + } } } @@ -192,6 +197,7 @@ public static class MembarOp extends AArch64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MembarOp.class); + // For future use. @SuppressWarnings("unused") private final int barriers; public MembarOp(int barriers) { @@ -200,14 +206,15 @@ } @Override - public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + // The odd-looking @SuppressWarnings("all") is here because of + // a compiler bug which warns that crb is unused, and also + // warns that @SuppressWarnings("unused") is unnecessary. + public void emitCode(@SuppressWarnings("all") CompilationResultBuilder crb, AArch64MacroAssembler masm) { // As I understand it load acquire/store release have the same semantics as on IA64 // and allow us to handle LoadStore, LoadLoad and StoreStore without an explicit // barrier. // But Graal support to figure out if a load/store is volatile is non-existant so for - // now - // just use - // memory barriers everywhere. + // now just use memory barriers everywhere. // if ((barrier & MemoryBarriers.STORE_LOAD) != 0) { masm.dmb(AArch64MacroAssembler.BarrierKind.ANY_ANY); // } @@ -408,7 +415,7 @@ } } - private static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { + static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { AArch64Address dest = loadStackSlotAddress(crb, masm, asStackSlot(result), Value.ILLEGAL); Register src = asRegister(input); // use the slot kind to define the operand size @@ -421,7 +428,7 @@ } } - private static void stack2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { + static void stack2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { AArch64Kind kind = (AArch64Kind) input.getPlatformKind(); // use the slot kind to define the operand size final int size = kind.getSizeInBytes() * Byte.SIZE; @@ -466,6 +473,12 @@ case Float: if (AArch64MacroAssembler.isFloatImmediate(input.asFloat())) { masm.fmov(32, dst, input.asFloat()); + } else if (crb.compilationResult.isImmutablePIC()) { + try (ScratchRegister scr = masm.getScratchRegister()) { + Register scratch = scr.getRegister(); + masm.mov(scratch, Float.floatToRawIntBits(input.asFloat())); + masm.fmov(32, dst, scratch); + } } else { masm.fldr(32, dst, (AArch64Address) crb.asFloatConstRef(input)); } @@ -473,6 +486,12 @@ case Double: if (AArch64MacroAssembler.isDoubleImmediate(input.asDouble())) { masm.fmov(64, dst, input.asDouble()); + } else if (crb.compilationResult.isImmutablePIC()) { + try (ScratchRegister scr = masm.getScratchRegister()) { + Register scratch = scr.getRegister(); + masm.mov(scratch, Double.doubleToRawLongBits(input.asDouble())); + masm.fmov(64, dst, scratch); + } } else { masm.fldr(64, dst, (AArch64Address) crb.asDoubleConstRef(input)); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64RestoreRegistersOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64RestoreRegistersOp.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; +import static jdk.vm.ci.code.ValueUtil.asStackSlot; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; + +import java.util.Arrays; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.LIRValueUtil; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.meta.AllocatableValue; + +/** + * Restores registers from stack slots. + */ +@Opcode("RESTORE_REGISTER") +public class AArch64RestoreRegistersOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64RestoreRegistersOp.class); + + /** + * The slots from which the registers are restored. + */ + @Use(STACK) protected final AllocatableValue[] slots; + + /** + * The operation that saved the registers restored by this operation. + */ + private final AArch64SaveRegistersOp save; + + public AArch64RestoreRegistersOp(AllocatableValue[] values, AArch64SaveRegistersOp save) { + this(TYPE, values, save); + } + + protected AArch64RestoreRegistersOp(LIRInstructionClass c, AllocatableValue[] values, AArch64SaveRegistersOp save) { + super(c); + assert Arrays.asList(values).stream().allMatch(LIRValueUtil::isVirtualStackSlot); + this.slots = values; + this.save = save; + } + + protected Register[] getSavedRegisters() { + return save.savedRegisters; + } + + protected void restoreRegister(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, StackSlot input) { + AArch64Move.stack2reg(crb, masm, result.asValue(), input); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register[] savedRegisters = getSavedRegisters(); + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i]; + restoreRegister(crb, masm, savedRegisters[i], asStackSlot(slots[i])); + } + } + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SaveRegistersOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SaveRegistersOp.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asStackSlot; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; + +import java.util.Arrays; + +import jdk.internal.vm.compiler.collections.EconomicSet; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.LIRValueUtil; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.framemap.FrameMap; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterSaveLayout; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.meta.AllocatableValue; + +/** + * Saves registers to stack slots. + */ +@Opcode("SAVE_REGISTER") +public class AArch64SaveRegistersOp extends AArch64LIRInstruction implements SaveRegistersOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64SaveRegistersOp.class); + + /** + * The registers (potentially) saved by this operation. + */ + protected final Register[] savedRegisters; + + /** + * The slots to which the registers are saved. + */ + @Def(STACK) protected final AllocatableValue[] slots; + + /** + * Specifies if {@link #remove(EconomicSet)} should have an effect. + */ + protected final boolean supportsRemove; + + /** + * + * @param savedRegisters the registers saved by this operation which may be subject to + * {@linkplain #remove(EconomicSet) pruning} + * @param savedRegisterLocations the slots to which the registers are saved + * @param supportsRemove determines if registers can be {@linkplain #remove(EconomicSet) pruned} + */ + public AArch64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { + this(TYPE, savedRegisters, savedRegisterLocations, supportsRemove); + } + + public AArch64SaveRegistersOp(LIRInstructionClass c, Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { + super(c); + assert Arrays.asList(savedRegisterLocations).stream().allMatch(LIRValueUtil::isVirtualStackSlot); + this.savedRegisters = savedRegisters; + this.slots = savedRegisterLocations; + this.supportsRemove = supportsRemove; + } + + protected void saveRegister(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot result, Register input) { + AArch64Move.reg2stack(crb, masm, result, input.asValue()); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i]; + saveRegister(crb, masm, asStackSlot(slots[i]), savedRegisters[i]); + } + } + } + + public AllocatableValue[] getSlots() { + return slots; + } + + @Override + public boolean supportsRemove() { + return supportsRemove; + } + + @Override + public int remove(EconomicSet doNotSave) { + if (!supportsRemove) { + throw new UnsupportedOperationException(); + } + return prune(doNotSave, savedRegisters); + } + + static int prune(EconomicSet toRemove, Register[] registers) { + int pruned = 0; + for (int i = 0; i < registers.length; i++) { + if (registers[i] != null) { + if (toRemove.contains(registers[i])) { + registers[i] = null; + pruned++; + } + } + } + return pruned; + } + + @Override + public RegisterSaveLayout getMap(FrameMap frameMap) { + int total = 0; + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + total++; + } + } + Register[] keys = new Register[total]; + int[] values = new int[total]; + if (total != 0) { + int mapIndex = 0; + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + keys[mapIndex] = savedRegisters[i]; + assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i]; + StackSlot slot = asStackSlot(slots[i]); + values[mapIndex] = indexForStackSlot(frameMap, slot); + mapIndex++; + } + } + assert mapIndex == total; + } + return new RegisterSaveLayout(keys, values); + } + + /** + * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack + * slots in the reference map. + * + * @param slot a stack slot + * @return the index of the stack slot + */ + private static int indexForStackSlot(FrameMap frameMap, StackSlot slot) { + assert frameMap.offsetForStackSlot(slot) % frameMap.getTarget().wordSize == 0; + int value = frameMap.offsetForStackSlot(slot) / frameMap.getTarget().wordSize; + return value; + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Thu May 31 13:39:26 2018 -0700 @@ -431,6 +431,12 @@ masm.lock(); } switch (accessKind) { + case BYTE: + masm.cmpxchgb(asRegister(newValue), address.toAddress()); + break; + case WORD: + masm.cmpxchgw(asRegister(newValue), address.toAddress()); + break; case DWORD: masm.cmpxchgl(asRegister(newValue), address.toAddress()); break; @@ -468,6 +474,12 @@ masm.lock(); } switch (accessKind) { + case BYTE: + masm.xaddb(address.toAddress(), asRegister(result)); + break; + case WORD: + masm.xaddw(address.toAddress(), asRegister(result)); + break; case DWORD: masm.xaddl(address.toAddress(), asRegister(result)); break; @@ -502,6 +514,12 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { move(accessKind, crb, masm, result, newValue); switch (accessKind) { + case BYTE: + masm.xchgb(asRegister(result), address.toAddress()); + break; + case WORD: + masm.xchgw(asRegister(result), address.toAddress()); + break; case DWORD: masm.xchgl(asRegister(result), address.toAddress()); break; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Thu May 31 13:39:26 2018 -0700 @@ -142,17 +142,18 @@ void emitNullCheck(Value address, LIRFrameState state); - Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue); + Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue); - Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue); + Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue); /** * Emit an atomic read-and-add instruction. * * @param address address of the value to be read and written + * @param valueKind the access kind for the value to be written * @param delta the value to be added */ - default Value emitAtomicReadAndAdd(Value address, Value delta) { + default Value emitAtomicReadAndAdd(Value address, ValueKind valueKind, Value delta) { throw GraalError.unimplemented(); } @@ -160,9 +161,10 @@ * Emit an atomic read-and-write instruction. * * @param address address of the value to be read and written + * @param valueKind the access kind for the value to be written * @param newValue the new value to be written */ - default Value emitAtomicReadAndWrite(Value address, Value newValue) { + default Value emitAtomicReadAndWrite(Value address, ValueKind valueKind, Value newValue) { throw GraalError.unimplemented(); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Thu May 31 13:39:26 2018 -0700 @@ -116,12 +116,14 @@ Position firstPosition = successors.next(); AbstractBeginNode originalLoopBegin = BeginNode.begin(originalLoop.entryPoint()); firstPosition.set(newControlSplit, originalLoopBegin); + originalLoopBegin.setNodeSourcePosition(firstPosition.get(firstNode).getNodeSourcePosition()); while (successors.hasNext()) { Position position = successors.next(); // create a new loop duplicate and connect it. LoopFragmentWhole duplicateLoop = originalLoop.duplicate(); AbstractBeginNode newBegin = BeginNode.begin(duplicateLoop.entryPoint()); + newBegin.setNodeSourcePosition(position.get(firstNode).getNodeSourcePosition()); position.set(newControlSplit, newBegin); // For each cloned ControlSplitNode, simplify the proper path diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Thu May 31 13:39:26 2018 -0700 @@ -118,7 +118,7 @@ } // round-away-from-zero divison: (range + stride -/+ 1) / stride ValueNode denominator = add(graph, range, sub(graph, absStride, one)); - ValueNode div = unsignedDivBefore(graph, loop.entryPoint(), denominator, absStride); + ValueNode div = unsignedDivBefore(graph, loop.entryPoint(), denominator, absStride, null); if (assumePositive) { return div; @@ -251,7 +251,7 @@ } assert graph.getGuardsStage().allowsFloatingGuards(); overflowGuard = graph.unique(new GuardNode(cond, AbstractBeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true, - JavaConstant.NULL_POINTER)); // TODO gd: use speculation + JavaConstant.NULL_POINTER, null)); // TODO gd: use speculation loop.loopBegin().setOverflowGuard(overflowGuard); return overflowGuard; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Thu May 31 13:39:26 2018 -0700 @@ -543,6 +543,7 @@ } } + @SuppressWarnings("try") private AbstractBeginNode mergeEnds() { assert isDuplicate(); List endsToMerge = new LinkedList<>(); @@ -562,9 +563,11 @@ if (endsToMerge.size() == 1) { AbstractEndNode end = endsToMerge.get(0); assert end.hasNoUsages(); - newExit = graph.add(new BeginNode()); - end.replaceAtPredecessor(newExit); - end.safeDelete(); + try (DebugCloseable position = end.withNodeSourcePosition()) { + newExit = graph.add(new BeginNode()); + end.replaceAtPredecessor(newExit); + end.safeDelete(); + } } else { assert endsToMerge.size() > 1; AbstractMergeNode newExitMerge = graph.add(new MergeNode()); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java Thu May 31 13:39:26 2018 -0700 @@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; import org.graalvm.compiler.nodes.calc.UnsignedDivNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import java.util.function.BiFunction; @@ -73,12 +74,12 @@ return BinaryArithmeticNode.sub(graph, v1, v2, NodeView.DEFAULT); } - public static ValueNode divBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor) { - return fixedDivBefore(graph, before, dividend, divisor, (dend, sor) -> SignedDivNode.create(dend, sor, NodeView.DEFAULT)); + public static ValueNode divBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor, GuardingNode zeroCheck) { + return fixedDivBefore(graph, before, dividend, divisor, (dend, sor) -> SignedDivNode.create(dend, sor, zeroCheck, NodeView.DEFAULT)); } - public static ValueNode unsignedDivBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor) { - return fixedDivBefore(graph, before, dividend, divisor, (dend, sor) -> UnsignedDivNode.create(dend, sor, NodeView.DEFAULT)); + public static ValueNode unsignedDivBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor, GuardingNode zeroCheck) { + return fixedDivBefore(graph, before, dividend, divisor, (dend, sor) -> UnsignedDivNode.create(dend, sor, zeroCheck, NodeView.DEFAULT)); } private static ValueNode fixedDivBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor, BiFunction createDiv) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java Thu May 31 13:39:26 2018 -0700 @@ -319,7 +319,8 @@ assert !graph.isFrozen(); ResolvedJavaMethod installedCodeOwner = graph.method(); request = new Request<>(graph, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, - graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default); + graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default, + true); } /** diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,13 +31,12 @@ import java.util.Set; import java.util.stream.Collectors; -import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.FilerException; -import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; @@ -45,11 +44,16 @@ import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; -import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.processor.AbstractProcessor; +/** + * Processor for {@value #NODE_INFO_CLASS_NAME} annotation. + */ @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({"org.graalvm.compiler.nodeinfo.NodeInfo"}) public class GraphNodeProcessor extends AbstractProcessor { + private static final String NODE_INFO_CLASS_NAME = "org.graalvm.compiler.nodeinfo.NodeInfo"; + @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); @@ -106,10 +110,6 @@ message(kind, element, "Exception thrown during processing: %s", buf.toString()); } - ProcessingEnvironment getProcessingEnv() { - return processingEnv; - } - boolean isNodeType(Element element) { if (element.getKind() != ElementKind.CLASS) { return false; @@ -134,17 +134,17 @@ GraphNodeVerifier verifier = new GraphNodeVerifier(this); - for (Element element : roundEnv.getElementsAnnotatedWith(NodeInfo.class)) { + for (Element element : roundEnv.getElementsAnnotatedWith(getTypeElement(NODE_INFO_CLASS_NAME))) { scope = element; try { if (!isNodeType(element)) { - errorMessage(element, "%s can only be applied to Node subclasses", NodeInfo.class.getSimpleName()); + errorMessage(element, "%s can only be applied to Node subclasses", getSimpleName(NODE_INFO_CLASS_NAME)); continue; } - NodeInfo nodeInfo = element.getAnnotation(NodeInfo.class); + AnnotationMirror nodeInfo = getAnnotation(element, getType(NODE_INFO_CLASS_NAME)); if (nodeInfo == null) { - errorMessage(element, "Cannot get %s annotation from annotated element", NodeInfo.class.getSimpleName()); + errorMessage(element, "Cannot get %s annotation from annotated element", getSimpleName(NODE_INFO_CLASS_NAME)); continue; } @@ -154,7 +154,7 @@ if (!modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.ABSTRACT)) { // TODO(thomaswue): Reenable this check. // errorMessage(element, "%s annotated class must be either final or abstract", - // NodeInfo.class.getSimpleName()); + // getSimpleName(NODE_INFO_CLASS_NAME)); // continue; } boolean found = false; @@ -167,7 +167,7 @@ } } if (!found) { - errorMessage(element, "%s annotated class must have a field named TYPE", NodeInfo.class.getSimpleName()); + errorMessage(element, "%s annotated class must have a field named TYPE", getSimpleName(NODE_INFO_CLASS_NAME)); } if (!typeElement.equals(verifier.Node) && !modifiers.contains(Modifier.ABSTRACT)) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeVerifier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeVerifier.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeVerifier.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.util.List; import java.util.Set; -import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; @@ -42,17 +41,16 @@ import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; import javax.lang.model.util.Types; +import org.graalvm.compiler.processor.AbstractProcessor; + /** * Verifies static constraints on nodes. */ public class GraphNodeVerifier { - private final GraphNodeProcessor env; - private final Types types; - private final Elements elements; + private final AbstractProcessor processor; // Checkstyle: stop private final TypeElement Input; @@ -67,12 +65,8 @@ // Checkstyle: resume - public GraphNodeVerifier(GraphNodeProcessor processor) { - this.env = processor; - - this.types = processor.getProcessingEnv().getTypeUtils(); - this.elements = processor.getProcessingEnv().getElementUtils(); - + public GraphNodeVerifier(AbstractProcessor processor) { + this.processor = processor; this.Input = getTypeElement("org.graalvm.compiler.graph.Node.Input"); this.OptionalInput = getTypeElement("org.graalvm.compiler.graph.Node.OptionalInput"); this.Successor = getTypeElement("org.graalvm.compiler.graph.Node.Successor"); @@ -88,11 +82,7 @@ * @throw {@link NoClassDefFoundError} if a type element does not exist for {@code name} */ public TypeElement getTypeElement(String name) { - TypeElement typeElement = elements.getTypeElement(name); - if (typeElement == null) { - throw new NoClassDefFoundError(name); - } - return typeElement; + return processor.getTypeElement(name); } public TypeElement getTypeElement(Class cls) { @@ -103,11 +93,8 @@ return getTypeElement(name).asType(); } - public ProcessingEnvironment getProcessingEnv() { - return env.getProcessingEnv(); - } - public boolean isAssignableWithErasure(Element from, Element to) { + Types types = processor.env().getTypeUtils(); TypeMirror fromType = types.erasure(from.asType()); TypeMirror toType = types.erasure(to.asType()); return types.isAssignable(fromType, toType); @@ -204,12 +191,12 @@ } private boolean sameType(TypeMirror type1, TypeMirror type2) { - return env.getProcessingEnv().getTypeUtils().isSameType(type1, type2); + return processor.env().getTypeUtils().isSameType(type1, type2); } private TypeElement getSuperType(TypeElement element) { if (element.getSuperclass() != null) { - return (TypeElement) env.getProcessingEnv().getTypeUtils().asElement(element.getSuperclass()); + return processor.asTypeElement(element.getSuperclass()); } return null; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java Thu May 31 13:39:26 2018 -0700 @@ -27,7 +27,11 @@ import static org.junit.Assert.assertFalse; import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp; @@ -582,4 +586,58 @@ assertEquals(longStamp.join(longEmpty), longEmpty); assertEquals(longStamp.meet(longEmpty), longStamp); } + + @Test + public void testUnaryOpFoldEmpty() { + // boolean?, byte, short, int, long + Stream.of(1, 8, 16, 32, 64).map(bits -> StampFactory.forInteger(bits).empty()).forEach(empty -> { + for (ArithmeticOpTable.UnaryOp op : IntegerStamp.OPS.getUnaryOps()) { + if (op != null) { + Assert.assertTrue(op.foldStamp(empty).isEmpty()); + } + } + }); + } + + @Test + public void testIntegerConvertOpWithEmpty() { + int[] bits = new int[]{1, 8, 16, 32, 64}; + + List> extendOps = Arrays.asList( + IntegerStamp.OPS.getSignExtend(), + IntegerStamp.OPS.getZeroExtend()); + + for (int inputBits : bits) { + IntegerStamp emptyIn = StampFactory.forInteger(inputBits).empty(); + for (int outputBits : bits) { + IntegerStamp emptyOut = StampFactory.forInteger(outputBits).empty(); + if (inputBits <= outputBits) { + for (IntegerConvertOp stamp : extendOps) { + IntegerStamp folded = (IntegerStamp) stamp.foldStamp(inputBits, outputBits, emptyIn); + Assert.assertTrue(folded.isEmpty()); + Assert.assertEquals(outputBits, folded.getBits()); + + // Widening is lossless, inversion is well-defined. + IntegerStamp inverted = (IntegerStamp) stamp.invertStamp(inputBits, outputBits, emptyOut); + Assert.assertTrue(inverted.isEmpty()); + Assert.assertEquals(inputBits, inverted.getBits()); + } + } + + if (inputBits >= outputBits) { + IntegerConvertOp narrow = IntegerStamp.OPS.getNarrow(); + IntegerStamp folded = (IntegerStamp) narrow.foldStamp(inputBits, outputBits, emptyIn); + Assert.assertTrue(folded.isEmpty()); + Assert.assertEquals(outputBits, folded.getBits()); + + // Narrowing is lossy, inversion can potentially yield empty or unknown (null). + IntegerStamp inverted = (IntegerStamp) narrow.invertStamp(inputBits, outputBits, emptyOut); + Assert.assertTrue(inverted == null || inverted.isEmpty()); + if (inverted != null) { + Assert.assertEquals(inputBits, inverted.getBits()); + } + } + } + } + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractFixedGuardNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractFixedGuardNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractFixedGuardNode.java Thu May 31 13:39:26 2018 -0700 @@ -25,6 +25,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.spi.Simplifiable; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; @@ -46,6 +47,7 @@ protected DeoptimizationAction action; protected JavaConstant speculation; protected boolean negated; + protected NodeSourcePosition noDeoptSuccessorPosition; @Override public LogicNode getCondition() { @@ -73,6 +75,12 @@ this.reason = deoptReason; } + protected AbstractFixedGuardNode(NodeClass c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, + boolean negated, NodeSourcePosition noDeoptSuccessorPosition) { + this(c, condition, deoptReason, action, speculation, negated); + this.noDeoptSuccessorPosition = noDeoptSuccessorPosition; + } + @Override public DeoptimizationReason getReason() { return reason; @@ -126,6 +134,7 @@ ifNode = graph().add(new IfNode(condition, currentNext, deopt, 1)); noDeoptSuccessor = ifNode.trueSuccessor(); } + noDeoptSuccessor.setNodeSourcePosition(getNoDeoptSuccessorPosition()); ((FixedWithNextNode) predecessor()).setNext(ifNode); this.replaceAtUsages(noDeoptSuccessor); GraphUtil.killWithUnusedFloatingInputs(this); @@ -148,4 +157,14 @@ public void setReason(DeoptimizationReason reason) { this.reason = reason; } + + @Override + public NodeSourcePosition getNoDeoptSuccessorPosition() { + return noDeoptSuccessorPosition; + } + + @Override + public void setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition) { + this.noDeoptSuccessorPosition = noDeoptSuccessorPosition; + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractMergeNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractMergeNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractMergeNode.java Thu May 31 13:39:26 2018 -0700 @@ -28,6 +28,7 @@ import java.util.List; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -158,6 +159,7 @@ * canonicalization. */ @Override + @SuppressWarnings("try") public void simplify(SimplifierTool tool) { FixedNode currentNext = next(); if (currentNext instanceof AbstractEndNode) { @@ -190,12 +192,14 @@ tool.addToWorkList(end); } AbstractEndNode newEnd; - if (merge instanceof LoopBeginNode) { - newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge)); - } else { - EndNode tmpEnd = graph().add(new EndNode()); - merge.addForwardEnd(tmpEnd); - newEnd = tmpEnd; + try (DebugCloseable position = end.withNodeSourcePosition()) { + if (merge instanceof LoopBeginNode) { + newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge)); + } else { + EndNode tmpEnd = graph().add(new EndNode()); + merge.addForwardEnd(tmpEnd); + newEnd = tmpEnd; + } } for (PhiNode phi : merge.phis()) { ValueNode v = phi.valueAt(origLoopEnd); @@ -233,11 +237,13 @@ ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result(); List endNodes = forwardEnds().snapshot(); for (EndNode end : endNodes) { - ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); - if (tool != null) { - tool.addToWorkList(end.predecessor()); + try (DebugCloseable position = returnNode.withNodeSourcePosition()) { + ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); + if (tool != null) { + tool.addToWorkList(end.predecessor()); + } + end.replaceAtPredecessor(newReturn); } - end.replaceAtPredecessor(newReturn); } GraphUtil.killCFG(this); for (EndNode end : endNodes) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java Thu May 31 13:39:26 2018 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.nodes; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.extended.GuardingNode; /** @@ -35,4 +36,16 @@ void setCondition(LogicNode x, boolean negated); boolean isNegated(); + + NodeSourcePosition getNoDeoptSuccessorPosition(); + + void setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition); + + default void addCallerToNoDeoptSuccessorPosition(NodeSourcePosition caller) { + NodeSourcePosition noDeoptSuccessorPosition = getNoDeoptSuccessorPosition(); + if (noDeoptSuccessorPosition == null) { + return; + } + setNoDeoptSuccessorPosition(new NodeSourcePosition(caller, noDeoptSuccessorPosition.getMethod(), noDeoptSuccessorPosition.getBCI())); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Thu May 31 13:39:26 2018 -0700 @@ -23,12 +23,14 @@ package org.graalvm.compiler.nodes; import org.graalvm.compiler.debug.DebugCloseable; + import static org.graalvm.compiler.nodeinfo.InputType.Guard; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -50,10 +52,18 @@ this(condition, deoptReason, action, JavaConstant.NULL_POINTER, negated); } + public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated, NodeSourcePosition noDeoptSuccessorPosition) { + this(condition, deoptReason, action, JavaConstant.NULL_POINTER, negated, noDeoptSuccessorPosition); + } + public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated) { super(TYPE, condition, deoptReason, action, speculation, negated); } + public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated, NodeSourcePosition noDeoptSuccessorPosition) { + super(TYPE, condition, deoptReason, action, speculation, negated, noDeoptSuccessorPosition); + } + @Override public void simplify(SimplifierTool tool) { super.simplify(tool); @@ -75,8 +85,10 @@ } else if (getCondition() instanceof ShortCircuitOrNode) { ShortCircuitOrNode shortCircuitOr = (ShortCircuitOrNode) getCondition(); if (isNegated() && hasNoUsages()) { - graph().addAfterFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getY(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isYNegated()))); - graph().replaceFixedWithFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getX(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isXNegated()))); + graph().addAfterFixed(this, + graph().add(new FixedGuardNode(shortCircuitOr.getY(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isYNegated(), getNoDeoptSuccessorPosition()))); + graph().replaceFixedWithFixed(this, + graph().add(new FixedGuardNode(shortCircuitOr.getX(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isXNegated(), getNoDeoptSuccessorPosition()))); } } } @@ -87,7 +99,7 @@ try (DebugCloseable position = this.withNodeSourcePosition()) { if (graph().getGuardsStage().allowsFloatingGuards()) { if (getAction() != DeoptimizationAction.None) { - ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode(); + ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated(), getNoDeoptSuccessorPosition()).asNode(); this.replaceAtUsages(guard); graph().removeFixed(this); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu May 31 13:39:26 2018 -0700 @@ -1022,7 +1022,11 @@ } } if (graph.trackNodeSourcePosition() && position != null) { - node.setNodeSourcePosition(methodScope.getCallerBytecodePosition(position)); + NodeSourcePosition callerBytecodePosition = methodScope.getCallerBytecodePosition(position); + node.setNodeSourcePosition(callerBytecodePosition); + if (node instanceof DeoptimizingGuard) { + ((DeoptimizingGuard) node).addCallerToNoDeoptSuccessorPosition(callerBytecodePosition.getCaller()); + } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardNode.java Thu May 31 13:39:26 2018 -0700 @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -63,19 +64,22 @@ protected DeoptimizationAction action; protected JavaConstant speculation; protected boolean negated; + protected NodeSourcePosition noDeoptSuccessorPosition; - public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, JavaConstant speculation) { - this(TYPE, condition, anchor, reason, action, negated, speculation); + public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, JavaConstant speculation, + NodeSourcePosition noDeoptSuccessorPosition) { + this(TYPE, condition, anchor, reason, action, negated, speculation, noDeoptSuccessorPosition); } protected GuardNode(NodeClass c, LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, - JavaConstant speculation) { + JavaConstant speculation, NodeSourcePosition noDeoptSuccessorPosition) { super(c, StampFactory.forVoid(), anchor); this.condition = condition; this.reason = reason; this.action = action; this.negated = negated; this.speculation = speculation; + this.noDeoptSuccessorPosition = noDeoptSuccessorPosition; } /** @@ -130,7 +134,7 @@ public Node canonical(CanonicalizerTool tool) { if (getCondition() instanceof LogicNegationNode) { LogicNegationNode negation = (LogicNegationNode) getCondition(); - return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation); + return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation, noDeoptSuccessorPosition); } if (getCondition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) getCondition(); @@ -158,4 +162,14 @@ public void setReason(DeoptimizationReason reason) { this.reason = reason; } + + @Override + public NodeSourcePosition getNoDeoptSuccessorPosition() { + return noDeoptSuccessorPosition; + } + + @Override + public void setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition) { + this.noDeoptSuccessorPosition = noDeoptSuccessorPosition; + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu May 31 13:39:26 2018 -0700 @@ -29,18 +29,25 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Objects; import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.Equivalence; +import org.graalvm.compiler.bytecode.BytecodeDisassembler; +import org.graalvm.compiler.bytecode.Bytecodes; +import org.graalvm.compiler.bytecode.Bytes; +import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.Simplifiable; @@ -67,6 +74,7 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.PrimitiveConstant; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -170,6 +178,60 @@ return super.verify(); } + private boolean compareCallContext(NodeSourcePosition successorPosition) { + NodeSourcePosition position = getNodeSourcePosition(); + NodeSourcePosition successor = successorPosition; + while (position != null) { + assertTrue(Objects.equals(position.getMethod(), successor.getMethod()), "method mismatch"); + position = position.getCaller(); + successor = successor.getCaller(); + } + assertTrue(successor == null, "successor position has more methods"); + return true; + } + + @Override + public boolean verifySourcePosition() { + NodeSourcePosition sourcePosition = getNodeSourcePosition(); + assertTrue(sourcePosition != null, "missing IfNode source position"); + + NodeSourcePosition trueSuccessorPosition = trueSuccessor.getNodeSourcePosition(); + assertTrue(trueSuccessorPosition != null, "missing IfNode true successor source position"); + + NodeSourcePosition falseSuccessorPosition = falseSuccessor.getNodeSourcePosition(); + assertTrue(falseSuccessorPosition != null, "missing IfNode false successor source position"); + + int bci = sourcePosition.getBCI(); + ResolvedJavaMethod method = sourcePosition.getMethod(); + int bytecode = BytecodeDisassembler.getBytecodeAt(method, bci); + + if (!Bytecodes.isIfBytecode(bytecode)) { + return true; + } + + byte[] code = (new ResolvedJavaMethodBytecode(method)).getCode(); + int targetBCI = bci + Bytes.beS2(code, bci + 1); + int nextBCI = bci + Bytecodes.lengthOf(bytecode); + + // At least one successor should have the correct BCI to indicate any possible negation that + // occurred after bytecode parsing + boolean matchingSuccessorFound = false; + if (trueSuccessorPosition.getBCI() == nextBCI || trueSuccessorPosition.getBCI() == targetBCI) { + assertTrue(compareCallContext(trueSuccessorPosition), "call context different from IfNode in trueSuccessor"); + matchingSuccessorFound = true; + } + + if (falseSuccessorPosition.getBCI() == nextBCI || falseSuccessorPosition.getBCI() == targetBCI) { + assertTrue(compareCallContext(falseSuccessorPosition), "call context different from IfNode in falseSuccessor"); + matchingSuccessorFound = true; + } + + assertTrue(matchingSuccessorFound, "no matching successor position found in IfNode"); + assertTrue(trueSuccessorPosition.getBCI() != falseSuccessorPosition.getBCI(), "successor positions same in IfNode"); + + return true; + } + public void eliminateNegation() { AbstractBeginNode oldTrueSuccessor = trueSuccessor; AbstractBeginNode oldFalseSuccessor = falseSuccessor; @@ -249,6 +311,11 @@ nextIf.setFalseSuccessor(intermediateBegin); intermediateBegin.setNext(this); this.setFalseSuccessor(bothFalseBegin); + + NodeSourcePosition intermediateBeginPosition = intermediateBegin.getNodeSourcePosition(); + intermediateBegin.setNodeSourcePosition(bothFalseBegin.getNodeSourcePosition()); + bothFalseBegin.setNodeSourcePosition(intermediateBeginPosition); + nextIf.setTrueSuccessorProbability(probabilityB); if (probabilityB == 1.0) { this.setTrueSuccessorProbability(0.0); @@ -477,6 +544,7 @@ * @param tool * @return true if a replacement was done. */ + @SuppressWarnings("try") private boolean checkForUnsignedCompare(SimplifierTool tool) { assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages(); if (condition() instanceof IntegerLessThanNode) { @@ -516,18 +584,20 @@ } } if (below != null) { - ifNode2.setTrueSuccessor(null); - ifNode2.setFalseSuccessor(null); + try (DebugCloseable position = ifNode2.withNodeSourcePosition()) { + ifNode2.setTrueSuccessor(null); + ifNode2.setFalseSuccessor(null); - IfNode newIfNode = graph().add(new IfNode(below, falseSucc, trueSucc, 1 - trueSuccessorProbability)); - // Remove the < 0 test. - tool.deleteBranch(trueSuccessor); - graph().removeSplit(this, falseSuccessor); + IfNode newIfNode = graph().add(new IfNode(below, falseSucc, trueSucc, 1 - trueSuccessorProbability)); + // Remove the < 0 test. + tool.deleteBranch(trueSuccessor); + graph().removeSplit(this, falseSuccessor); - // Replace the second test with the new one. - ifNode2.predecessor().replaceFirstSuccessor(ifNode2, newIfNode); - ifNode2.safeDelete(); - return true; + // Replace the second test with the new one. + ifNode2.predecessor().replaceFirstSuccessor(ifNode2, newIfNode); + ifNode2.safeDelete(); + return true; + } } } } @@ -850,6 +920,7 @@ * * @param tool */ + @SuppressWarnings("try") private boolean splitIfAtPhi(SimplifierTool tool) { if (graph().getGuardsStage().areFrameStatesAtSideEffects()) { // Disabled until we make sure we have no FrameState-less merges at this stage @@ -918,12 +989,16 @@ } else if (result != condition) { // Build a new IfNode using the new condition BeginNode trueBegin = graph().add(new BeginNode()); + trueBegin.setNodeSourcePosition(trueSuccessor().getNodeSourcePosition()); BeginNode falseBegin = graph().add(new BeginNode()); + falseBegin.setNodeSourcePosition(falseSuccessor().getNodeSourcePosition()); if (result.graph() == null) { result = graph().addOrUniqueWithInputs(result); + result.setNodeSourcePosition(condition.getNodeSourcePosition()); } IfNode newIfNode = graph().add(new IfNode(result, trueBegin, falseBegin, trueSuccessorProbability)); + newIfNode.setNodeSourcePosition(getNodeSourcePosition()); merge.removeEnd(end); ((FixedWithNextNode) end.predecessor()).setNext(newIfNode); @@ -1053,6 +1128,7 @@ } } + @SuppressWarnings("try") private MergeNode insertMerge(AbstractBeginNode begin) { MergeNode merge = graph().add(new MergeNode()); if (!begin.anchored().isEmpty()) { @@ -1066,9 +1142,11 @@ AbstractBeginNode theBegin = begin; if (begin instanceof LoopExitNode) { // Insert an extra begin to make it easier. - theBegin = graph().add(new BeginNode()); - begin.replaceAtPredecessor(theBegin); - theBegin.setNext(begin); + try (DebugCloseable position = begin.withNodeSourcePosition()) { + theBegin = graph().add(new BeginNode()); + begin.replaceAtPredecessor(theBegin); + theBegin.setNext(begin); + } } FixedNode next = theBegin.next(); next.replaceAtPredecessor(merge); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Thu May 31 13:39:26 2018 -0700 @@ -225,9 +225,11 @@ while (replacementEntries.advance()) { Invokable replacementInvoke = replacementEntries.getKey(); Callsite replacementSite = replacementEntries.getValue(); - Invokable invoke = (Invokable) replacements.get((Node) replacementInvoke); - Callsite site = mapping.get(replacementSite); - leaves.put(invoke, site); + if (replacementInvoke.isAlive()) { + Invokable invoke = (Invokable) replacements.get((Node) replacementInvoke); + Callsite site = mapping.get(replacementSite); + leaves.put(invoke, site); + } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNegationNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNegationNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNegationNode.java Thu May 31 13:39:26 2018 -0700 @@ -31,6 +31,8 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import jdk.vm.ci.meta.TriState; + /** * Logic node that negates its argument. */ @@ -77,4 +79,11 @@ return this; } + @Override + public TriState implies(boolean thisNegated, LogicNode other) { + if (other == getValue()) { + return TriState.get(thisNegated); + } + return getValue().implies(!thisNegated, other); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNode.java Thu May 31 13:39:26 2018 -0700 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.nodeinfo.InputType.Condition; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import jdk.vm.ci.meta.TriState; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node.IndirectCanonicalization; import org.graalvm.compiler.graph.NodeClass; @@ -75,4 +76,19 @@ return false; } + + /** + * Determines what this condition implies about the other. + * + *

+ * + * @param thisNegated whether this condition should be considered as false. + * @param other the other condition. + */ + public TriState implies(boolean thisNegated, LogicNode other) { + return TriState.UNKNOWN; + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java Thu May 31 13:39:26 2018 -0700 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -310,13 +311,16 @@ return loopEnds().first(); } + @SuppressWarnings("try") public void removeExits() { for (LoopExitNode loopexit : loopExits().snapshot()) { - loopexit.removeProxies(); - FrameState loopStateAfter = loopexit.stateAfter(); - graph().replaceFixedWithFixed(loopexit, graph().add(new BeginNode())); - if (loopStateAfter != null) { - GraphUtil.tryKillUnused(loopStateAfter); + try (DebugCloseable position = graph().withNodeSourcePosition(loopexit)) { + loopexit.removeProxies(); + FrameState loopStateAfter = loopexit.stateAfter(); + graph().replaceFixedWithFixed(loopexit, graph().add(new BeginNode())); + if (loopStateAfter != null) { + GraphUtil.tryKillUnused(loopStateAfter); + } } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Thu May 31 13:39:26 2018 -0700 @@ -46,7 +46,7 @@ @Input ValueNode length; @Override - public ValueNode length() { + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { return length; } @@ -57,7 +57,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (GraphUtil.arrayLength(object()) != length()) { + if (GraphUtil.arrayLength(object(), ArrayLengthProvider.FindLengthMode.SEARCH_ONLY) != length) { return this; } return super.canonical(tool); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ShortCircuitOrNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ShortCircuitOrNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ShortCircuitOrNode.java Thu May 31 13:39:26 2018 -0700 @@ -26,15 +26,19 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; +import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.calc.IntegerBelowNode; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; + +import jdk.vm.ci.meta.TriState; @NodeInfo(cycles = CYCLES_0, size = SIZE_0) public final class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary { - public static final NodeClass TYPE = NodeClass.create(ShortCircuitOrNode.class); @Input(Condition) LogicNode x; @Input(Condition) LogicNode y; @@ -169,9 +173,90 @@ return optimizeShortCircuit(inner, this.yNegated, this.xNegated, false); } } + + // !X => Y constant + TriState impliedForY = forX.implies(!isXNegated(), forY); + if (impliedForY.isKnown()) { + boolean yResult = impliedForY.toBoolean() ^ isYNegated(); + return yResult + ? LogicConstantNode.tautology() + : (isXNegated() + ? LogicNegationNode.create(forX) + : forX); + } + + // if X >= 0: + // u < 0 || X < u ==>> X |<| u + if (!isXNegated() && !isYNegated()) { + LogicNode sym = simplifyComparison(forX, forY); + if (sym != null) { + return sym; + } + } + + // if X >= 0: + // X |<| u || X < u ==>> X |<| u + if (forX instanceof IntegerBelowNode && forY instanceof IntegerLessThanNode && !isXNegated() && !isYNegated()) { + IntegerBelowNode xNode = (IntegerBelowNode) forX; + IntegerLessThanNode yNode = (IntegerLessThanNode) forY; + ValueNode xxNode = xNode.getX(); // X >= 0 + ValueNode yxNode = yNode.getX(); // X >= 0 + if (xxNode == yxNode && ((IntegerStamp) xxNode.stamp(NodeView.DEFAULT)).isPositive()) { + ValueNode xyNode = xNode.getY(); // u + ValueNode yyNode = yNode.getY(); // u + if (xyNode == yyNode) { + return forX; + } + } + } + + // if X >= 0: + // u < 0 || (X < u || tail) ==>> X |<| u || tail + if (forY instanceof ShortCircuitOrNode && !isXNegated() && !isYNegated()) { + ShortCircuitOrNode yNode = (ShortCircuitOrNode) forY; + if (!yNode.isXNegated()) { + LogicNode sym = simplifyComparison(forX, yNode.getX()); + if (sym != null) { + double p1 = getShortCircuitProbability(); + double p2 = yNode.getShortCircuitProbability(); + return new ShortCircuitOrNode(sym, isXNegated(), yNode.getY(), yNode.isYNegated(), p1 + (1 - p1) * p2); + } + } + } + return this; } + private static LogicNode simplifyComparison(LogicNode forX, LogicNode forY) { + LogicNode sym = simplifyComparisonOrdered(forX, forY); + if (sym == null) { + return simplifyComparisonOrdered(forY, forX); + } + return sym; + } + + private static LogicNode simplifyComparisonOrdered(LogicNode forX, LogicNode forY) { + // if X is >= 0: + // u < 0 || X < u ==>> X |<| u + if (forX instanceof IntegerLessThanNode && forY instanceof IntegerLessThanNode) { + IntegerLessThanNode xNode = (IntegerLessThanNode) forX; + IntegerLessThanNode yNode = (IntegerLessThanNode) forY; + ValueNode xyNode = xNode.getY(); // 0 + if (xyNode.isConstant() && IntegerStamp.OPS.getAdd().isNeutral(xyNode.asConstant())) { + ValueNode yxNode = yNode.getX(); // X >= 0 + IntegerStamp stamp = (IntegerStamp) yxNode.stamp(NodeView.DEFAULT); + if (stamp.isPositive()) { + if (xNode.getX() == yNode.getY()) { + ValueNode u = xNode.getX(); + return IntegerBelowNode.create(yxNode, u, NodeView.DEFAULT); + } + } + } + } + + return null; + } + private static LogicNode optimizeShortCircuit(ShortCircuitOrNode inner, boolean innerNegated, boolean matchNegated, boolean matchIsInnerX) { boolean innerMatchNegated; if (matchIsInnerX) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu May 31 13:39:26 2018 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -273,55 +274,60 @@ return new CanonicalizeToNullNode(node.stamp); } + @SuppressWarnings("try") private void handleCanonicalization(LoopScope loopScope, int nodeOrderId, FixedNode node, Node c) { assert c != node : "unnecessary call"; - Node canonical = c == null ? canonicalizeFixedNodeToNull(node) : c; - if (!canonical.isAlive()) { - assert !canonical.isDeleted(); - canonical = graph.addOrUniqueWithInputs(canonical); - if (canonical instanceof FixedWithNextNode) { - graph.addBeforeFixed(node, (FixedWithNextNode) canonical); - } else if (canonical instanceof ControlSinkNode) { - FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor(); - predecessor.setNext((ControlSinkNode) canonical); - List successorSnapshot = node.successors().snapshot(); - node.safeDelete(); - for (Node successor : successorSnapshot) { - successor.safeDelete(); + try (DebugCloseable position = graph.withNodeSourcePosition(node)) { + Node canonical = c == null ? canonicalizeFixedNodeToNull(node) : c; + if (!canonical.isAlive()) { + assert !canonical.isDeleted(); + canonical = graph.addOrUniqueWithInputs(canonical); + if (canonical instanceof FixedWithNextNode) { + graph.addBeforeFixed(node, (FixedWithNextNode) canonical); + } else if (canonical instanceof ControlSinkNode) { + FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor(); + predecessor.setNext((ControlSinkNode) canonical); + List successorSnapshot = node.successors().snapshot(); + node.safeDelete(); + for (Node successor : successorSnapshot) { + successor.safeDelete(); + } + } else { + assert !(canonical instanceof FixedNode); } - - } else { - assert !(canonical instanceof FixedNode); } + if (!node.isDeleted()) { + GraphUtil.unlinkFixedNode((FixedWithNextNode) node); + node.replaceAtUsagesAndDelete(canonical); + } + assert lookupNode(loopScope, nodeOrderId) == node; + registerNode(loopScope, nodeOrderId, canonical, true, false); } - if (!node.isDeleted()) { - GraphUtil.unlinkFixedNode((FixedWithNextNode) node); - node.replaceAtUsagesAndDelete(canonical); - } - assert lookupNode(loopScope, nodeOrderId) == node; - registerNode(loopScope, nodeOrderId, canonical, true, false); } @Override + @SuppressWarnings("try") protected Node handleFloatingNodeBeforeAdd(MethodScope methodScope, LoopScope loopScope, Node node) { if (node instanceof ValueNode) { ((ValueNode) node).inferStamp(); } if (node instanceof Canonicalizable) { - Node canonical = ((Canonicalizable) node).canonical(canonicalizerTool); - if (canonical == null) { - /* - * This is a possible return value of canonicalization. However, we might need to - * add additional usages later on for which we need a node. Therefore, we just do - * nothing and leave the node in place. - */ - } else if (canonical != node) { - if (!canonical.isAlive()) { - assert !canonical.isDeleted(); - canonical = graph.addOrUniqueWithInputs(canonical); + try (DebugCloseable context = graph.withNodeSourcePosition(node)) { + Node canonical = ((Canonicalizable) node).canonical(canonicalizerTool); + if (canonical == null) { + /* + * This is a possible return value of canonicalization. However, we might need + * to add additional usages later on for which we need a node. Therefore, we + * just do nothing and leave the node in place. + */ + } else if (canonical != node) { + if (!canonical.isAlive()) { + assert !canonical.isDeleted(); + canonical = graph.addOrUniqueWithInputs(canonical); + } + assert node.hasNoUsages(); + return canonical; } - assert node.hasNoUsages(); - return canonical; } } return node; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java Thu May 31 13:39:26 2018 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.nodes.spi.ValueProxy; import jdk.vm.ci.meta.TriState; @@ -52,7 +53,58 @@ public void generate(NodeLIRBuilderTool gen) { } + /** + * In general the input stamp cannot be trusted, this method is reserved for the cases when it's + * "safe" to use the input stamp. To ensure safety use + * {@link #getSucceedingStampForValue(boolean)} instead. + */ + public Stamp getSucceedingStampForValue(boolean negated, Stamp valueStamp) { + Stamp succStamp = getSucceedingStampForValue(negated); + if (succStamp != null) { + succStamp = succStamp.join(valueStamp); + } + return succStamp; + } + + /** + * The input stamp cannot be trusted, the returned stamp cannot use the input stamp to narrow + * itself or derive any assumptions. This method does not use the input stamp and is considered + * safe. + * + * It's responsibility of the caller to determine when it's "safe" to "trust" the input stamp + * and use {@link #getSucceedingStampForValue(boolean, Stamp)} instead. + */ public abstract Stamp getSucceedingStampForValue(boolean negated); public abstract TriState tryFold(Stamp valueStamp); + + @Override + public TriState implies(boolean thisNegated, LogicNode other) { + if (other instanceof UnaryOpLogicNode) { + UnaryOpLogicNode unaryY = (UnaryOpLogicNode) other; + if (this.getValue() == unaryY.getValue() || // fast path + skipThroughPisAndProxies(this.getValue()) == skipThroughPisAndProxies(unaryY.getValue())) { + Stamp succStamp = this.getSucceedingStampForValue(thisNegated); + TriState fold = unaryY.tryFold(succStamp); + if (fold.isKnown()) { + return fold; + } + } + } + return super.implies(thisNegated, other); + } + + private static ValueNode skipThroughPisAndProxies(ValueNode node) { + ValueNode n = node; + while (n != null) { + if (n instanceof PiNode) { + n = ((PiNode) n).getOriginalNode(); + } else if (n instanceof ValueProxy) { + n = ((ValueProxy) n).getOriginalNode(); + } else { + break; + } + } + return n; + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java Thu May 31 13:39:26 2018 -0700 @@ -29,16 +29,14 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.type.StampTool; -import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.util.CollectionsUtil; /** * Value {@link PhiNode}s merge data flow values at control flow merges. */ @NodeInfo(nameTemplate = "Phi({i#values}, {p#valueDescription})") -public class ValuePhiNode extends PhiNode implements ArrayLengthProvider { +public class ValuePhiNode extends PhiNode { public static final NodeClass TYPE = NodeClass.create(ValuePhiNode.class); @Input protected NodeInputList values; @@ -80,26 +78,6 @@ } @Override - public ValueNode length() { - if (merge() instanceof LoopBeginNode) { - return null; - } - ValueNode length = null; - for (ValueNode input : values()) { - ValueNode l = GraphUtil.arrayLength(input); - if (l == null) { - return null; - } - if (length == null) { - length = l; - } else if (length != l) { - return null; - } - } - return length; - } - - @Override public boolean verify() { Stamp s = null; for (ValueNode input : values()) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Thu May 31 13:39:26 2018 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; @@ -38,6 +39,7 @@ import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.TriState; @NodeInfo(shortName = "|<|") public final class IntegerBelowNode extends IntegerLowerThanNode { @@ -135,4 +137,36 @@ return new IntegerBelowNode(x, y); } } + + @Override + public TriState implies(boolean thisNegated, LogicNode other) { + if (other instanceof LogicNegationNode) { + // Unwrap negations. + TriState result = implies(thisNegated, ((LogicNegationNode) other).getValue()); + if (result.isKnown()) { + return TriState.get(!result.toBoolean()); + } + } + if (!thisNegated) { + if (other instanceof IntegerLessThanNode) { + IntegerLessThanNode integerLessThanNode = (IntegerLessThanNode) other; + IntegerStamp stampL = (IntegerStamp) this.getY().stamp(NodeView.DEFAULT); + // if L >= 0: + if (stampL.isPositive()) { // L >= 0 + if (this.getX() == integerLessThanNode.getX()) { + // x |<| L implies x < L + if (this.getY() == integerLessThanNode.getY()) { + return TriState.TRUE; + } + // x |<| L implies !(x < 0) + if (integerLessThanNode.getY().isConstant() && + IntegerStamp.OPS.getAdd().isNeutral(integerLessThanNode.getY().asConstant())) { + return TriState.FALSE; + } + } + } + } + } + return super.implies(thisNegated, other); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java Thu May 31 13:39:26 2018 -0700 @@ -28,9 +28,11 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -49,19 +51,26 @@ UNSIGNED } + @OptionalInput(InputType.Guard) private GuardingNode zeroCheck; + private final Op op; private final Type type; private final boolean canDeopt; - protected IntegerDivRemNode(NodeClass c, Stamp stamp, Op op, Type type, ValueNode x, ValueNode y) { + protected IntegerDivRemNode(NodeClass c, Stamp stamp, Op op, Type type, ValueNode x, ValueNode y, GuardingNode zeroCheck) { super(c, stamp, x, y); + this.zeroCheck = zeroCheck; this.op = op; this.type = type; // Assigning canDeopt during constructor, because it must never change during lifetime of // the node. IntegerStamp yStamp = (IntegerStamp) getY().stamp(NodeView.DEFAULT); - this.canDeopt = yStamp.contains(0) || yStamp.contains(-1); + this.canDeopt = (yStamp.contains(0) && zeroCheck == null) || yStamp.contains(-1); + } + + public final GuardingNode getZeroCheck() { + return zeroCheck; } public final Op getOp() { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Thu May 31 13:39:26 2018 -0700 @@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -41,16 +42,16 @@ public static final NodeClass TYPE = NodeClass.create(SignedDivNode.class); - protected SignedDivNode(ValueNode x, ValueNode y) { - this(TYPE, x, y); + protected SignedDivNode(ValueNode x, ValueNode y, GuardingNode zeroCheck) { + this(TYPE, x, y, zeroCheck); } - protected SignedDivNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, IntegerStamp.OPS.getDiv().foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), Op.DIV, Type.SIGNED, x, y); + protected SignedDivNode(NodeClass c, ValueNode x, ValueNode y, GuardingNode zeroCheck) { + super(c, IntegerStamp.OPS.getDiv().foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), Op.DIV, Type.SIGNED, x, y, zeroCheck); } - public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { - return canonical(null, x, y, view); + public static ValueNode create(ValueNode x, ValueNode y, GuardingNode zeroCheck, NodeView view) { + return canonical(null, x, y, zeroCheck, view); } @Override @@ -61,17 +62,17 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - return canonical(this, forX, forY, view); + return canonical(this, forX, forY, getZeroCheck(), view); } - public static ValueNode canonical(SignedDivNode self, ValueNode forX, ValueNode forY, NodeView view) { + public static ValueNode canonical(SignedDivNode self, ValueNode forX, ValueNode forY, GuardingNode zeroCheck, NodeView view) { Stamp predictedStamp = IntegerStamp.OPS.getDiv().foldStamp(forX.stamp(NodeView.DEFAULT), forY.stamp(NodeView.DEFAULT)); Stamp stamp = self != null ? self.stamp(view) : predictedStamp; if (forX.isConstant() && forY.isConstant()) { long y = forY.asJavaConstant().asLong(); if (y == 0) { - return self != null ? self : new SignedDivNode(forX, forY); // this will trap, can - // not canonicalize + /* This will trap, cannot canonicalize. */ + return self != null ? self : new SignedDivNode(forX, forY, zeroCheck); } return ConstantNode.forIntegerStamp(stamp, forX.asJavaConstant().asLong() / y); } else if (forY.isConstant()) { @@ -89,7 +90,7 @@ SignedRemNode integerRemNode = (SignedRemNode) integerSubNode.getY(); if (integerSubNode.stamp(view).isCompatible(stamp) && integerRemNode.stamp(view).isCompatible(stamp) && integerSubNode.getX() == integerRemNode.getX() && forY == integerRemNode.getY()) { - SignedDivNode sd = new SignedDivNode(integerSubNode.getX(), forY); + SignedDivNode sd = new SignedDivNode(integerSubNode.getX(), forY, zeroCheck); sd.stateBefore = self != null ? self.stateBefore : null; return sd; } @@ -103,7 +104,7 @@ } } - return self != null ? self : new SignedDivNode(forX, forY); + return self != null ? self : new SignedDivNode(forX, forY, zeroCheck); } public static ValueNode canonical(ValueNode forX, long c, NodeView view) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java Thu May 31 13:39:26 2018 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -40,17 +41,17 @@ public static final NodeClass TYPE = NodeClass.create(SignedRemNode.class); - protected SignedRemNode(ValueNode x, ValueNode y) { - this(TYPE, x, y); + protected SignedRemNode(ValueNode x, ValueNode y, GuardingNode zeroCheck) { + this(TYPE, x, y, zeroCheck); } - protected SignedRemNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, IntegerStamp.OPS.getRem().foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), Op.REM, Type.SIGNED, x, y); + protected SignedRemNode(NodeClass c, ValueNode x, ValueNode y, GuardingNode zeroCheck) { + super(c, IntegerStamp.OPS.getRem().foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), Op.REM, Type.SIGNED, x, y, zeroCheck); } - public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + public static ValueNode create(ValueNode x, ValueNode y, GuardingNode zeroCheck, NodeView view) { Stamp stamp = IntegerStamp.OPS.getRem().foldStamp(x.stamp(view), y.stamp(view)); - return canonical(null, x, y, stamp, view); + return canonical(null, x, y, zeroCheck, stamp, view); } @Override @@ -61,15 +62,15 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - return canonical(this, forX, forY, stamp(view), view); + return canonical(this, forX, forY, getZeroCheck(), stamp(view), view); } - private static ValueNode canonical(SignedRemNode self, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { + private static ValueNode canonical(SignedRemNode self, ValueNode forX, ValueNode forY, GuardingNode zeroCheck, Stamp stamp, NodeView view) { if (forX.isConstant() && forY.isConstant()) { long y = forY.asJavaConstant().asLong(); if (y == 0) { - return self != null ? self : new SignedRemNode(forX, forY); // this will trap, can - // not canonicalize + /* This will trap, cannot canonicalize. */ + return self != null ? self : new SignedRemNode(forX, forY, zeroCheck); } return ConstantNode.forIntegerStamp(stamp, forX.asJavaConstant().asLong() % y); } else if (forY.isConstant() && forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) { @@ -78,7 +79,7 @@ IntegerStamp yStamp = (IntegerStamp) forY.stamp(view); if (constY < 0 && constY != CodeUtil.minValue(yStamp.getBits())) { Stamp newStamp = IntegerStamp.OPS.getRem().foldStamp(forX.stamp(view), forY.stamp(view)); - return canonical(null, forX, ConstantNode.forIntegerStamp(yStamp, -constY), newStamp, view); + return canonical(null, forX, ConstantNode.forIntegerStamp(yStamp, -constY), zeroCheck, newStamp, view); } if (constY == 1) { @@ -96,7 +97,7 @@ } } } - return self != null ? self : new SignedRemNode(forX, forY); + return self != null ? self : new SignedRemNode(forX, forY, zeroCheck); } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java Thu May 31 13:39:26 2018 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -40,33 +41,33 @@ public static final NodeClass TYPE = NodeClass.create(UnsignedDivNode.class); - public UnsignedDivNode(ValueNode x, ValueNode y) { - this(TYPE, x, y); + public UnsignedDivNode(ValueNode x, ValueNode y, GuardingNode zeroCheck) { + this(TYPE, x, y, zeroCheck); } - protected UnsignedDivNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, x.stamp(NodeView.DEFAULT).unrestricted(), Op.DIV, Type.UNSIGNED, x, y); + protected UnsignedDivNode(NodeClass c, ValueNode x, ValueNode y, GuardingNode zeroCheck) { + super(c, x.stamp(NodeView.DEFAULT).unrestricted(), Op.DIV, Type.UNSIGNED, x, y, zeroCheck); } - public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + public static ValueNode create(ValueNode x, ValueNode y, GuardingNode zeroCheck, NodeView view) { Stamp stamp = x.stamp(view).unrestricted(); - return canonical(null, x, y, stamp, view); + return canonical(null, x, y, zeroCheck, stamp, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - return canonical(this, forX, forY, stamp(view), view); + return canonical(this, forX, forY, getZeroCheck(), stamp(view), view); } @SuppressWarnings("unused") - private static ValueNode canonical(UnsignedDivNode self, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { + private static ValueNode canonical(UnsignedDivNode self, ValueNode forX, ValueNode forY, GuardingNode zeroCheck, Stamp stamp, NodeView view) { int bits = ((IntegerStamp) stamp).getBits(); if (forX.isConstant() && forY.isConstant()) { long yConst = CodeUtil.zeroExtend(forY.asJavaConstant().asLong(), bits); if (yConst == 0) { - return self != null ? self : new UnsignedDivNode(forX, forY); // this will trap, - // cannot canonicalize + /* This will trap, cannot canonicalize. */ + return self != null ? self : new UnsignedDivNode(forX, forY, zeroCheck); } return ConstantNode.forIntegerStamp(stamp, Long.divideUnsigned(CodeUtil.zeroExtend(forX.asJavaConstant().asLong(), bits), yConst)); } else if (forY.isConstant()) { @@ -78,7 +79,7 @@ return new UnsignedRightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(c))); } } - return self != null ? self : new UnsignedDivNode(forX, forY); + return self != null ? self : new UnsignedDivNode(forX, forY, zeroCheck); } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java Thu May 31 13:39:26 2018 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -40,33 +41,33 @@ public static final NodeClass TYPE = NodeClass.create(UnsignedRemNode.class); - public UnsignedRemNode(ValueNode x, ValueNode y) { - this(TYPE, x, y); + public UnsignedRemNode(ValueNode x, ValueNode y, GuardingNode zeroCheck) { + this(TYPE, x, y, zeroCheck); } - protected UnsignedRemNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, x.stamp(NodeView.DEFAULT).unrestricted(), Op.REM, Type.UNSIGNED, x, y); + protected UnsignedRemNode(NodeClass c, ValueNode x, ValueNode y, GuardingNode zeroCheck) { + super(c, x.stamp(NodeView.DEFAULT).unrestricted(), Op.REM, Type.UNSIGNED, x, y, zeroCheck); } - public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + public static ValueNode create(ValueNode x, ValueNode y, GuardingNode zeroCheck, NodeView view) { Stamp stamp = x.stamp(view).unrestricted(); - return canonical(null, x, y, stamp, view); + return canonical(null, x, y, zeroCheck, stamp, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - return canonical(this, forX, forY, stamp(view), view); + return canonical(this, forX, forY, getZeroCheck(), stamp(view), view); } @SuppressWarnings("unused") - public static ValueNode canonical(UnsignedRemNode self, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { + public static ValueNode canonical(UnsignedRemNode self, ValueNode forX, ValueNode forY, GuardingNode zeroCheck, Stamp stamp, NodeView view) { int bits = ((IntegerStamp) stamp).getBits(); if (forX.isConstant() && forY.isConstant()) { long yConst = CodeUtil.zeroExtend(forY.asJavaConstant().asLong(), bits); if (yConst == 0) { - return self != null ? self : new UnsignedRemNode(forX, forY); // this will trap, - // cannot canonicalize + /* This will trap, cannot canonicalize. */ + return self != null ? self : new UnsignedRemNode(forX, forY, zeroCheck); } return ConstantNode.forIntegerStamp(stamp, Long.remainderUnsigned(CodeUtil.zeroExtend(forX.asJavaConstant().asLong(), bits), yConst)); } else if (forY.isConstant()) { @@ -77,7 +78,7 @@ return new AndNode(forX, ConstantNode.forIntegerStamp(stamp, c - 1)); } } - return self != null ? self : new UnsignedRemNode(forX, forY); + return self != null ? self : new UnsignedRemNode(forX, forY, zeroCheck); } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java Thu May 31 13:39:26 2018 -0700 @@ -91,7 +91,9 @@ } protected VirtualBoxingNode createVirtualBoxingNode() { - return new VirtualBoxingNode(StampTool.typeOrNull(stamp(NodeView.DEFAULT)), boxingKind); + VirtualBoxingNode node = new VirtualBoxingNode(StampTool.typeOrNull(stamp(NodeView.DEFAULT)), boxingKind); + node.setNodeSourcePosition(getNodeSourcePosition()); + return node; } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Thu May 31 13:39:26 2018 -0700 @@ -28,8 +28,12 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.ValueNode; @@ -50,26 +54,43 @@ cyclesRationale = "Node will be lowered to a foreign call.", size = SIZE_8) // @formatter:on -public final class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { +public final class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single, Canonicalizable { + + public enum BytecodeExceptionKind { + NULL_POINTER(0, NullPointerException.class), + OUT_OF_BOUNDS(2, ArrayIndexOutOfBoundsException.class), + CLASS_CAST(2, ClassCastException.class), + ARRAY_STORE(1, ArrayStoreException.class), + DIVISION_BY_ZERO(0, ArithmeticException.class); + + final int numArguments; + final Class exceptionClass; + + BytecodeExceptionKind(int numArguments, Class exceptionClass) { + this.numArguments = numArguments; + this.exceptionClass = exceptionClass; + } + } public static final NodeClass TYPE = NodeClass.create(BytecodeExceptionNode.class); - protected final Class exceptionClass; + protected final BytecodeExceptionKind exceptionKind; @Input NodeInputList arguments; - public BytecodeExceptionNode(MetaAccessProvider metaAccess, Class exceptionClass, ValueNode... arguments) { - super(TYPE, StampFactory.objectNonNull(TypeReference.createExactTrusted(metaAccess.lookupJavaType(exceptionClass)))); - this.exceptionClass = exceptionClass; + public BytecodeExceptionNode(MetaAccessProvider metaAccess, BytecodeExceptionKind exceptionKind, ValueNode... arguments) { + super(TYPE, StampFactory.objectNonNull(TypeReference.createExactTrusted(metaAccess.lookupJavaType(exceptionKind.exceptionClass)))); + this.exceptionKind = exceptionKind; this.arguments = new NodeInputList<>(this, arguments); + GraalError.guarantee(arguments.length == exceptionKind.numArguments, "Mismatch in argument count for BytecodeExceptionNode"); } - public Class getExceptionClass() { - return exceptionClass; + public BytecodeExceptionKind getExceptionKind() { + return exceptionKind; } @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name) { - return super.toString(verbosity) + "#" + exceptionClass.getSimpleName(); + return super.toString(verbosity) + "#" + exceptionKind; } return super.toString(verbosity); } @@ -80,6 +101,14 @@ } @Override + public Node canonical(CanonicalizerTool tool) { + if (tool.allUsagesAvailable() && getUsageCount() == 0) { + return null; + } + return this; + } + + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadArrayComponentHubNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadArrayComponentHubNode.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.nodes.extended; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; + +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.Lowerable; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.nodes.spi.StampProvider; + +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * Loads the component hub for of the provided array hub. + * + * This is a fixed node because on certain VMs, for example the HotSpot VM, the read is only valid + * when the provided hub is actually an array hub (and not, e.g., a primitive hub), so this node + * must not float above a possible type check. Properly guarding this node would be possible too, + * but it is unlikely that the guard would be more flexible than just fixing the node in the control + * flow. + */ +@NodeInfo(cycles = CYCLES_2, size = SIZE_1) +public final class LoadArrayComponentHubNode extends FixedWithNextNode implements Lowerable, Canonicalizable.Unary { + + public static final NodeClass TYPE = NodeClass.create(LoadArrayComponentHubNode.class); + + private @Input ValueNode value; + + public static ValueNode create(ValueNode value, StampProvider stampProvider, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + Stamp stamp = stampProvider.createHubStamp(null); + return findSynonym(null, value, stamp, metaAccess, constantReflection); + } + + protected LoadArrayComponentHubNode(Stamp stamp, ValueNode value) { + super(TYPE, stamp); + this.value = value; + } + + @Override + public ValueNode getValue() { + return value; + } + + @Override + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } + + @Override + public Node canonical(CanonicalizerTool tool, ValueNode forValue) { + return findSynonym(this, forValue, stamp, tool.getMetaAccess(), tool.getConstantReflection()); + } + + private static ValueNode findSynonym(LoadArrayComponentHubNode self, ValueNode forValue, Stamp stamp, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + if (forValue.isConstant()) { + ResolvedJavaType type = constantReflection.asJavaType(forValue.asConstant()); + if (type != null) { + return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(type.getComponentType()), metaAccess); + } + } + return self != null ? self : new LoadArrayComponentHubNode(stamp, forValue); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -22,17 +22,29 @@ */ package org.graalvm.compiler.nodes.graphbuilderconf; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +/** + * Abstract class for a plugin generated for a method annotated by {@link NodeIntrinsic} or + * {@link Fold}. + */ public abstract class GeneratedInvocationPlugin implements InvocationPlugin { + /** + * Gets the class of the annotation for which this plugin was generated. + */ + public abstract Class getSource(); + @Override public abstract boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java Thu May 31 13:39:26 2018 -0700 @@ -76,4 +76,10 @@ * by an intrinsic. */ boolean parsingIntrinsic(); + + @SuppressWarnings("unused") + default boolean canDeferPlugin(GeneratedInvocationPlugin plugin) { + // By default generated plugins must be completely processed during parsing. + return false; + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -84,6 +84,15 @@ } /** + * Determines if this plugin only decorates the method is it associated with. That is, it + * inserts nodes prior to the invocation (e.g. some kind of marker nodes) but still expects the + * parser to process the invocation further. + */ + default boolean isDecorator() { + return false; + } + + /** * Handles invocation of a signature polymorphic method. * * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static @@ -167,7 +176,8 @@ * @return {@code true} if this plugin handled the invocation of {@code targetMethod} * {@code false} if the graph builder should process the invoke further (e.g., by * inlining it or creating an {@link Invoke} node). A plugin that does not handle an - * invocation must not modify the graph being constructed. + * invocation must not modify the graph being constructed unless it is a + * {@linkplain InvocationPlugin#isDecorator() decorator}. */ default boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { if (isSignaturePolymorphic()) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Thu May 31 13:39:26 2018 -0700 @@ -679,7 +679,9 @@ } } if (res != null) { - if (canBeIntrinsified(declaringClass)) { + // A decorator plugin is trusted since it does not replace + // the method it intrinsifies. + if (res.isDecorator() || canBeIntrinsified(declaringClass)) { return res; } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java Thu May 31 13:39:26 2018 -0700 @@ -23,6 +23,7 @@ package org.graalvm.compiler.nodes.graphbuilderconf; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaTypeProfile; @@ -106,10 +107,12 @@ * @param b the context * @param array the accessed array * @param index the index for the array access + * @param boundsCheck the explicit bounds check already emitted, or null if no bounds check was + * emitted yet * @param elementKind the element kind of the accessed array * @return true if the plugin handles the array access, false otherwise. */ - default boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind) { + default boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { return false; } @@ -119,11 +122,15 @@ * @param b the context * @param array the accessed array * @param index the index for the array access + * @param boundsCheck the explicit array bounds check already emitted, or null if no array + * bounds check was emitted yet + * @param storeCheck the explicit array store check already emitted, or null if no array store + * check was emitted yet * @param elementKind the element kind of the accessed array * @param value the value to be stored into the array * @return true if the plugin handles the array access, false otherwise. */ - default boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind, ValueNode value) { + default boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind elementKind, ValueNode value) { return false; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java Thu May 31 13:39:26 2018 -0700 @@ -38,8 +38,12 @@ public static final NodeClass TYPE = NodeClass.create(AbstractNewArrayNode.class); @Input protected ValueNode length; + public ValueNode length() { + return length; + } + @Override - public ValueNode length() { + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { return length; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AccessIndexedNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AccessIndexedNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AccessIndexedNode.java Thu May 31 13:39:26 2018 -0700 @@ -24,8 +24,10 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -40,6 +42,7 @@ public static final NodeClass TYPE = NodeClass.create(AccessIndexedNode.class); @Input protected ValueNode index; + @OptionalInput(InputType.Guard) private GuardingNode boundsCheck; protected final JavaKind elementKind; public ValueNode index() { @@ -52,14 +55,21 @@ * @param stamp the result kind of the access * @param array the instruction producing the array * @param index the instruction producing the index + * @param boundsCheck the explicit array bounds check already performed before the access, or + * null if no check was performed yet * @param elementKind the kind of the elements of the array */ - protected AccessIndexedNode(NodeClass c, Stamp stamp, ValueNode array, ValueNode index, JavaKind elementKind) { + protected AccessIndexedNode(NodeClass c, Stamp stamp, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { super(c, stamp, array); this.index = index; + this.boundsCheck = boundsCheck; this.elementKind = elementKind; } + public GuardingNode getBoundsCheck() { + return boundsCheck; + } + /** * Gets the element type of the array. * diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java Thu May 31 13:39:26 2018 -0700 @@ -33,10 +33,9 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.ValueProxyNode; +import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.ValueProxy; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -91,38 +90,14 @@ } /** - * Replicate the {@link ValueProxyNode}s from {@code originalValue} onto {@code value}. - * - * @param originalValue a possibly proxied value - * @param value a value needing proxies - * @return proxies wrapping {@code value} - */ - private static ValueNode reproxyValue(ValueNode originalValue, ValueNode value) { - if (value.isConstant()) { - // No proxy needed - return value; - } - if (originalValue instanceof ValueProxyNode) { - ValueProxyNode proxy = (ValueProxyNode) originalValue; - return new ValueProxyNode(reproxyValue(proxy.getOriginalNode(), value), proxy.proxyPoint()); - } else if (originalValue instanceof ValueProxy) { - ValueProxy proxy = (ValueProxy) originalValue; - return reproxyValue(proxy.getOriginalNode(), value); - } else { - return value; - } - } - - /** * Gets the length of an array if possible. * * @return a node representing the length of {@code array} or null if it is not available */ public static ValueNode readArrayLength(ValueNode originalArray, ConstantReflectionProvider constantReflection) { - ValueNode length = GraphUtil.arrayLength(originalArray); + ValueNode length = GraphUtil.arrayLength(originalArray, ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ); if (length != null) { - // Ensure that any proxies on the original value end up on the length value - return reproxyValue(originalArray, length); + return length; } return readArrayLengthConstant(originalArray, constantReflection); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Thu May 31 13:39:26 2018 -0700 @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; +import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -50,13 +51,19 @@ public static final NodeClass TYPE = NodeClass.create(AtomicReadAndAddNode.class); @Input(Association) AddressNode address; @Input ValueNode delta; + /** + * We explicitly track the kind of this node instead of using {#delta.getStackKind()} to be able + * to emit the memory access instruction with the correct number of bits. + */ + private JavaKind valueKind; protected final LocationIdentity locationIdentity; - public AtomicReadAndAddNode(AddressNode address, ValueNode delta, LocationIdentity locationIdentity) { - super(TYPE, StampFactory.forKind(delta.getStackKind())); + public AtomicReadAndAddNode(AddressNode address, ValueNode delta, JavaKind valueKind, LocationIdentity locationIdentity) { + super(TYPE, StampFactory.forKind(valueKind)); this.address = address; this.delta = delta; + this.valueKind = valueKind; this.locationIdentity = locationIdentity; } @@ -71,7 +78,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(gen.operand(address), gen.operand(delta)); + Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(gen.operand(address), gen.getLIRGeneratorTool().getValueKind(valueKind), gen.operand(delta)); gen.setResult(this, result); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java Thu May 31 13:39:26 2018 -0700 @@ -26,6 +26,8 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; +import java.util.Objects; + import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -50,8 +52,6 @@ import jdk.vm.ci.meta.JavaTypeProfile; import jdk.vm.ci.meta.TriState; -import java.util.Objects; - /** * The {@code InstanceOfNode} represents an instanceof test. */ @@ -219,4 +219,25 @@ assert this.checkedStamp.join(newCheckedStamp).equals(newCheckedStamp) : "stamp can only improve"; this.checkedStamp = newCheckedStamp; } + + @Override + public TriState implies(boolean thisNegated, LogicNode other) { + if (other instanceof InstanceOfNode) { + InstanceOfNode instanceOfNode = (InstanceOfNode) other; + if (instanceOfNode.getValue() == getValue()) { + if (thisNegated) { + // !X => Y + if (this.getCheckedStamp().meet(instanceOfNode.getCheckedStamp()).equals(this.getCheckedStamp())) { + return TriState.get(false); + } + } else { + // X => Y + if (instanceOfNode.getCheckedStamp().meet(this.getCheckedStamp()).equals(instanceOfNode.getCheckedStamp())) { + return TriState.get(true); + } + } + } + } + return super.implies(thisNegated, other); + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java Thu May 31 13:39:26 2018 -0700 @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.type.StampTool; @@ -65,20 +66,21 @@ * @param index the instruction producing the index * @param elementKind the element type */ - public LoadIndexedNode(Assumptions assumptions, ValueNode array, ValueNode index, JavaKind elementKind) { - this(TYPE, createStamp(assumptions, array, elementKind), array, index, elementKind); + public LoadIndexedNode(Assumptions assumptions, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { + this(TYPE, createStamp(assumptions, array, elementKind), array, index, boundsCheck, elementKind); } - public static ValueNode create(Assumptions assumptions, ValueNode array, ValueNode index, JavaKind elementKind, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + public static ValueNode create(Assumptions assumptions, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind, MetaAccessProvider metaAccess, + ConstantReflectionProvider constantReflection) { ValueNode constant = tryConstantFold(array, index, metaAccess, constantReflection); if (constant != null) { return constant; } - return new LoadIndexedNode(assumptions, array, index, elementKind); + return new LoadIndexedNode(assumptions, array, index, boundsCheck, elementKind); } - protected LoadIndexedNode(NodeClass c, Stamp stamp, ValueNode array, ValueNode index, JavaKind elementKind) { - super(c, stamp, array, index, elementKind); + protected LoadIndexedNode(NodeClass c, Stamp stamp, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { + super(c, stamp, array, index, boundsCheck, elementKind); } private static Stamp createStamp(Assumptions assumptions, ValueNode array, JavaKind kind) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java Thu May 31 13:39:26 2018 -0700 @@ -66,7 +66,7 @@ LIRKind resultKind = tool.getLIRKind(stamp(NodeView.DEFAULT)); Value trueResult = tool.emitConstant(resultKind, JavaConstant.TRUE); Value falseResult = tool.emitConstant(resultKind, JavaConstant.FALSE); - Value result = tool.emitLogicCompareAndSwap(gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), trueResult, falseResult); + Value result = tool.emitLogicCompareAndSwap(tool.getLIRKind(getAccessStamp()), gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), trueResult, falseResult); gen.setResult(this, result); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Thu May 31 13:39:26 2018 -0700 @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; +import jdk.vm.ci.meta.ValueKind; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -53,10 +54,12 @@ public static final NodeClass TYPE = NodeClass.create(LoweredAtomicReadAndWriteNode.class); @Input ValueNode newValue; @OptionalInput(State) FrameState stateAfter; + private final ValueKind valueKind; - public LoweredAtomicReadAndWriteNode(AddressNode address, LocationIdentity location, ValueNode newValue, BarrierType barrierType) { + public LoweredAtomicReadAndWriteNode(AddressNode address, LocationIdentity location, ValueNode newValue, ValueKind valueKind, BarrierType barrierType) { super(TYPE, address, location, newValue.stamp(NodeView.DEFAULT).unrestricted(), barrierType); this.newValue = newValue; + this.valueKind = valueKind; } @Override @@ -78,7 +81,10 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(gen.operand(getAddress()), gen.operand(getNewValue())); + Value emitted = gen.operand(getNewValue()); + // In case this node works with compressed objects, the newValue's kind must be used. + ValueKind> actualKind = newValue.stamp(NodeView.DEFAULT).getStackKind().isObject() ? emitted.getValueKind() : this.valueKind; + Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(gen.operand(getAddress()), actualKind, emitted); gen.setResult(this, result); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java Thu May 31 13:39:26 2018 -0700 @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Simplifiable; import org.graalvm.compiler.graph.spi.SimplifierTool; @@ -118,6 +119,7 @@ } @Override + @SuppressWarnings("try") public void simplify(SimplifierTool tool) { if (hasNoUsages()) { NodeView view = NodeView.from(tool); @@ -132,10 +134,12 @@ // Should be areFrameStatesAtSideEffects but currently SVM will complain about // RuntimeConstraint if (graph().getGuardsStage().allowsFloatingGuards()) { - LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), CanonicalCondition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view); - // we do not have a non-deopting path for that at the moment so action=None. - FixedGuardNode guard = graph().add(new FixedGuardNode(lengthNegativeCondition, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, true)); - graph().replaceFixedWithFixed(this, guard); + try (DebugCloseable context = this.withNodeSourcePosition()) { + LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), CanonicalCondition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view); + // we do not have a non-deopting path for that at the moment so action=None. + FixedGuardNode guard = graph().add(new FixedGuardNode(lengthNegativeCondition, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, true)); + graph().replaceFixedWithFixed(this, guard); + } } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewMultiArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewMultiArrayNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewMultiArrayNode.java Thu May 31 13:39:26 2018 -0700 @@ -87,7 +87,7 @@ } @Override - public ValueNode length() { + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { return dimension(0); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java Thu May 31 13:39:26 2018 -0700 @@ -28,10 +28,12 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; @@ -49,9 +51,15 @@ public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable { public static final NodeClass TYPE = NodeClass.create(StoreIndexedNode.class); + + @OptionalInput(InputType.Guard) private GuardingNode storeCheck; @Input ValueNode value; @OptionalInput(State) FrameState stateAfter; + public GuardingNode getStoreCheck() { + return storeCheck; + } + @Override public FrameState stateAfter() { return stateAfter; @@ -73,8 +81,9 @@ return value; } - public StoreIndexedNode(ValueNode array, ValueNode index, JavaKind elementKind, ValueNode value) { - super(TYPE, StampFactory.forVoid(), array, index, elementKind); + public StoreIndexedNode(ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind elementKind, ValueNode value) { + super(TYPE, StampFactory.forVoid(), array, index, boundsCheck, elementKind); + this.storeCheck = storeCheck; this.value = value; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndExchangeNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndExchangeNode.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.nodes.java; + +import jdk.vm.ci.meta.JavaKind; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; +import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; +import org.graalvm.compiler.nodes.spi.Lowerable; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import jdk.internal.vm.compiler.word.LocationIdentity; + +import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import static org.graalvm.compiler.nodeinfo.InputType.Value; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; + +/** + * Represents an atomic compare-and-swap operation. The result is the current value of the memory + * location that was compared. + */ +@NodeInfo(allowedUsageTypes = {Value, Memory}, cycles = CYCLES_8, size = SIZE_8) +public final class UnsafeCompareAndExchangeNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + + public static final NodeClass TYPE = NodeClass.create(UnsafeCompareAndExchangeNode.class); + @Input ValueNode object; + @Input ValueNode offset; + @Input ValueNode expected; + @Input ValueNode newValue; + + private final JavaKind valueKind; + private final LocationIdentity locationIdentity; + + public UnsafeCompareAndExchangeNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind valueKind, LocationIdentity locationIdentity) { + super(TYPE, expected.stamp(NodeView.DEFAULT).meet(newValue.stamp(NodeView.DEFAULT))); + assert expected.stamp(NodeView.DEFAULT).isCompatible(newValue.stamp(NodeView.DEFAULT)); + this.object = object; + this.offset = offset; + this.expected = expected; + this.newValue = newValue; + this.valueKind = valueKind; + this.locationIdentity = locationIdentity; + } + + public ValueNode object() { + return object; + } + + public ValueNode offset() { + return offset; + } + + public ValueNode expected() { + return expected; + } + + public ValueNode newValue() { + return newValue; + } + + public JavaKind getValueKind() { + return valueKind; + } + + @Override + public LocationIdentity getLocationIdentity() { + return locationIdentity; + } + + @Override + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java Thu May 31 13:39:26 2018 -0700 @@ -41,8 +41,8 @@ import jdk.vm.ci.meta.JavaKind; /** - * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the - * value matched the expected value. + * Represents an atomic compare-and-swap operation. The result is a boolean that contains whether + * the value matched the expected value. */ @NodeInfo(allowedUsageTypes = {Value, Memory}, cycles = CYCLES_8, size = SIZE_8) public final class UnsafeCompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java Thu May 31 13:39:26 2018 -0700 @@ -55,6 +55,6 @@ assert getNewValue().stamp(NodeView.DEFAULT).isCompatible(getExpectedValue().stamp(NodeView.DEFAULT)); LIRGeneratorTool tool = gen.getLIRGeneratorTool(); assert !this.canDeoptimize(); - gen.setResult(this, tool.emitValueCompareAndSwap(gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()))); + gen.setResult(this, tool.emitValueCompareAndSwap(tool.getLIRKind(getAccessStamp()), gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()))); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Thu May 31 13:39:26 2018 -0700 @@ -44,6 +44,7 @@ import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; @@ -122,7 +123,7 @@ } } if (locationIdentity.equals(ARRAY_LENGTH_LOCATION)) { - ValueNode length = GraphUtil.arrayLength(object); + ValueNode length = GraphUtil.arrayLength(object, ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ); if (length != null) { return length; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/ArrayLengthProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/ArrayLengthProvider.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/ArrayLengthProvider.java Thu May 31 13:39:26 2018 -0700 @@ -23,11 +23,45 @@ package org.graalvm.compiler.nodes.spi; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.ValuePhiNode; +import org.graalvm.compiler.nodes.ValueProxyNode; +import org.graalvm.compiler.nodes.util.GraphUtil; public interface ArrayLengthProvider { /** - * @return the length of the array described by this node, or null if it is not available + * The different modes that determine what the results of {@link GraphUtil#arrayLength} and + * {@link ArrayLengthProvider#findLength} can be used for. */ - ValueNode length(); + enum FindLengthMode { + /** + * Use the result of {@link GraphUtil#arrayLength} and + * {@link ArrayLengthProvider#findLength} to replace the explicit load of the array length + * with a node that does not involve a memory access of the array length. + * + * Values that are defined inside a loop and flow out the loop need to be proxied by + * {@link ValueProxyNode}. When this mode is used, new necessary proxy nodes are created + * base on the proxies that were found while traversing the path to the length node. In + * addition, new {@link ValuePhiNode phi nodes} can be created. The caller is responsible + * for adding these nodes to the graph, i.e., the return value can be a node that is not yet + * added to the graph. + */ + CANONICALIZE_READ, + + /** + * Use the result of {@link GraphUtil#arrayLength} and + * {@link ArrayLengthProvider#findLength} only for decisions whether a certain optimization + * is possible. No new nodes are created during the search, i.e., the result is either a + * node that is already in the graph, or null. + */ + SEARCH_ONLY + } + + /** + * Returns the length of the array described by this node, or null if it is not available. + * Details of the different modes are documented in {@link FindLengthMode}. + * + * This method should not be called directly. Use {@link GraphUtil#arrayLength} instead. + */ + ValueNode findLength(FindLengthMode mode); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringTool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringTool.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringTool.java Thu May 31 13:39:26 2018 -0700 @@ -23,6 +23,7 @@ package org.graalvm.compiler.nodes.spi; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.LogicNode; @@ -51,7 +52,8 @@ GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action); - GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated); + GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated, + NodeSourcePosition noDeoptSuccessorPosition); /** * Gets the closest fixed node preceding the node currently being lowered. diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu May 31 13:39:26 2018 -0700 @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.function.BiFunction; import jdk.internal.vm.compiler.collections.EconomicMap; @@ -66,10 +67,13 @@ import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.ValuePhiNode; +import org.graalvm.compiler.nodes.ValueProxyNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; +import org.graalvm.compiler.nodes.spi.ArrayLengthProvider.FindLengthMode; import org.graalvm.compiler.nodes.spi.LimitedValueProxy; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.ValueProxy; @@ -664,28 +668,71 @@ } /** - * Looks for an {@link ArrayLengthProvider} while iterating through all {@link ValueProxy - * ValueProxies}. + * Returns the length of the array described by the value parameter, or null if it is not + * available. Details of the different modes are documented in {@link FindLengthMode}. * * @param value The start value. + * @param mode The mode as documented in {@link FindLengthMode}. * @return The array length if one was found, or null otherwise. */ - public static ValueNode arrayLength(ValueNode value) { + public static ValueNode arrayLength(ValueNode value, ArrayLengthProvider.FindLengthMode mode) { + Objects.requireNonNull(mode); + ValueNode current = value; do { + /* + * PiArrayNode implements ArrayLengthProvider and ValueProxy. We want to treat it as an + * ArrayLengthProvider, therefore we check this case first. + */ if (current instanceof ArrayLengthProvider) { - ValueNode length = ((ArrayLengthProvider) current).length(); - if (length != null) { - return length; + return ((ArrayLengthProvider) current).findLength(mode); + + } else if (current instanceof ValuePhiNode) { + return phiArrayLength((ValuePhiNode) current, mode); + + } else if (current instanceof ValueProxyNode) { + ValueProxyNode proxy = (ValueProxyNode) current; + ValueNode length = arrayLength(proxy.getOriginalNode(), mode); + if (mode == ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ && length != null && !length.isConstant()) { + length = new ValueProxyNode(length, proxy.proxyPoint()); } - } - if (current instanceof ValueProxy) { + return length; + + } else if (current instanceof ValueProxy) { + /* Written as a loop instead of a recursive call to reduce recursion depth. */ current = ((ValueProxy) current).getOriginalNode(); + } else { - break; + return null; } } while (true); - return null; + } + + private static ValueNode phiArrayLength(ValuePhiNode phi, ArrayLengthProvider.FindLengthMode mode) { + if (phi.merge() instanceof LoopBeginNode) { + /* Avoid cycle detection by not processing phi functions that could introduce cycles. */ + return null; + } + + ValueNode singleLength = null; + for (int i = 0; i < phi.values().count(); i++) { + ValueNode input = phi.values().get(i); + ValueNode length = arrayLength(input, mode); + if (length == null) { + return null; + } + assert length.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Int; + + if (i == 0) { + assert singleLength == null; + singleLength = length; + } else if (singleLength == length) { + /* Nothing to do, still having a single length. */ + } else { + return null; + } + } + return singleLength; } /** @@ -1006,7 +1053,7 @@ } else { /* The source array is not virtualized, emit index loads. */ for (int i = 0; i < readLength; i++) { - LoadIndexedNode load = new LoadIndexedNode(null, sourceAlias, ConstantNode.forInt(i + fromInt, graph), elementKind); + LoadIndexedNode load = new LoadIndexedNode(null, sourceAlias, ConstantNode.forInt(i + fromInt, graph), null, elementKind); tool.addNode(load); newEntryState[i] = load; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java Thu May 31 13:39:26 2018 -0700 @@ -35,6 +35,7 @@ import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; +import org.graalvm.compiler.nodes.util.GraphUtil; /** * Selects one object from a {@link CommitAllocationNode}. The object is identified by its @@ -71,10 +72,7 @@ } @Override - public ValueNode length() { - if (virtualObject instanceof ArrayLengthProvider) { - return ((ArrayLengthProvider) virtualObject).length(); - } - return null; + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { + return GraphUtil.arrayLength(virtualObject, mode); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Thu May 31 13:39:26 2018 -0700 @@ -123,16 +123,20 @@ @Override public VirtualArrayNode duplicate() { - return new VirtualArrayNode(componentType, length); + VirtualArrayNode node = new VirtualArrayNode(componentType, length); + node.setNodeSourcePosition(this.getNodeSourcePosition()); + return node; } @Override public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { - return new AllocatedObjectNode(this); + AllocatedObjectNode node = new AllocatedObjectNode(this); + node.setNodeSourcePosition(this.getNodeSourcePosition()); + return node; } @Override - public ValueNode length() { + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { return ConstantNode.forInt(length); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualBoxingNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualBoxingNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualBoxingNode.java Thu May 31 13:39:26 2018 -0700 @@ -53,14 +53,19 @@ @Override public VirtualBoxingNode duplicate() { - return new VirtualBoxingNode(type(), boxingKind); + VirtualBoxingNode node = new VirtualBoxingNode(type(), boxingKind); + node.setNodeSourcePosition(this.getNodeSourcePosition()); + return node; } @Override public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { assert entries.length == 1; assert locks == null; - return new BoxNode(entries[0], type(), boxingKind); + + BoxNode node = new BoxNode(entries[0], type(), boxingKind); + node.setNodeSourcePosition(this.getNodeSourcePosition()); + return node; } public ValueNode getBoxedValue(VirtualizerTool tool) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Thu May 31 13:39:26 2018 -0700 @@ -113,11 +113,15 @@ @Override public VirtualInstanceNode duplicate() { - return new VirtualInstanceNode(type, fields, super.hasIdentity()); + VirtualInstanceNode node = new VirtualInstanceNode(type, fields, super.hasIdentity()); + node.setNodeSourcePosition(this.getNodeSourcePosition()); + return node; } @Override public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { - return new AllocatedObjectNode(this); + AllocatedObjectNode node = new AllocatedObjectNode(this); + node.setNodeSourcePosition(this.getNodeSourcePosition()); + return node; } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -35,11 +34,11 @@ import java.util.Map; import java.util.Set; -import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; @@ -50,21 +49,16 @@ import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionDescriptor; -import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.processor.AbstractProcessor; /** - * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors} + * Processes static fields annotated with {@code Option}. An {@code OptionDescriptors} * implementation is generated for each top level class containing at least one such field. The name * of the generated class for top level class {@code com.foo.Bar} is * {@code com.foo.Bar_OptionDescriptors}. @@ -72,6 +66,12 @@ @SupportedAnnotationTypes({"org.graalvm.compiler.options.Option"}) public class OptionProcessor extends AbstractProcessor { + private static final String OPTION_CLASS_NAME = "org.graalvm.compiler.options.Option"; + private static final String OPTION_KEY_CLASS_NAME = "org.graalvm.compiler.options.OptionKey"; + private static final String OPTION_TYPE_CLASS_NAME = "org.graalvm.compiler.options.OptionType"; + private static final String OPTION_DESCRIPTOR_CLASS_NAME = "org.graalvm.compiler.options.OptionDescriptor"; + private static final String OPTION_DESCRIPTORS_CLASS_NAME = "org.graalvm.compiler.options.OptionDescriptors"; + @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); @@ -79,6 +79,9 @@ private final Set processed = new HashSet<>(); + private TypeMirror optionTypeMirror; + private TypeMirror optionKeyTypeMirror; + private void processElement(Element element, OptionsInfo info) { if (!element.getModifiers().contains(Modifier.STATIC)) { @@ -90,26 +93,24 @@ return; } - Option annotation = element.getAnnotation(Option.class); + AnnotationMirror annotation = getAnnotation(element, optionTypeMirror); assert annotation != null; assert element instanceof VariableElement; assert element.getKind() == ElementKind.FIELD; VariableElement field = (VariableElement) element; String fieldName = field.getSimpleName().toString(); - Elements elements = processingEnv.getElementUtils(); Types types = processingEnv.getTypeUtils(); TypeMirror fieldType = field.asType(); if (fieldType.getKind() != TypeKind.DECLARED) { - processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OptionKey.class.getName(), element); + processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OPTION_KEY_CLASS_NAME, element); return; } DeclaredType declaredFieldType = (DeclaredType) fieldType; - TypeMirror optionKeyType = elements.getTypeElement(OptionKey.class.getName()).asType(); - if (!types.isSubtype(fieldType, types.erasure(optionKeyType))) { - String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionKeyType); + if (!types.isSubtype(fieldType, types.erasure(optionKeyTypeMirror))) { + String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionKeyTypeMirror); processingEnv.getMessager().printMessage(Kind.ERROR, msg, element); return; } @@ -123,7 +124,7 @@ return; } - String optionName = annotation.name(); + String optionName = getAnnotationValue(annotation, "name", String.class); if (optionName.equals("")) { optionName = fieldName; } @@ -134,7 +135,7 @@ } DeclaredType declaredOptionKeyType = declaredFieldType; - while (!types.isSameType(types.erasure(declaredOptionKeyType), types.erasure(optionKeyType))) { + while (!types.isSameType(types.erasure(declaredOptionKeyType), types.erasure(optionKeyTypeMirror))) { List directSupertypes = types.directSupertypes(declaredFieldType); assert !directSupertypes.isEmpty(); declaredOptionKeyType = (DeclaredType) directSupertypes.get(0); @@ -171,12 +172,12 @@ processingEnv.getMessager().printMessage(Kind.ERROR, "Option field cannot be declared in the unnamed package", element); return; } - String[] helpValue = annotation.help(); + List helpValue = getAnnotationValueList(annotation, "help", String.class); String help = ""; - String[] extraHelp = {}; + List extraHelp = new ArrayList<>(); - if (helpValue.length == 1) { - help = helpValue[0]; + if (helpValue.size() == 1) { + help = helpValue.get(0); if (help.startsWith("file:")) { String path = help.substring("file:".length()); Filer filer = processingEnv.getFiler(); @@ -194,12 +195,10 @@ help = ""; } String line = br.readLine(); - List lines = new ArrayList<>(); while (line != null) { - lines.add(line); + extraHelp.add(line); line = br.readLine(); } - extraHelp = lines.toArray(new String[lines.size()]); } } catch (IOException e) { String msg = String.format("Error reading %s containing the help text for option field: %s", path, e); @@ -207,9 +206,9 @@ return; } } - } else if (helpValue.length > 1) { - help = helpValue[0]; - extraHelp = Arrays.copyOfRange(helpValue, 1, helpValue.length); + } else if (helpValue.size() > 1) { + help = helpValue.get(0); + extraHelp = helpValue.subList(1, helpValue.size()); } if (help.length() != 0) { char firstChar = help.charAt(0); @@ -219,7 +218,8 @@ } } - info.options.add(new OptionInfo(optionName, annotation.type(), help, extraHelp, optionType, declaringClass, field)); + String optionTypeName = getAnnotationValue(annotation, "type", VariableElement.class).getSimpleName().toString(); + info.options.add(new OptionInfo(optionName, optionTypeName, help, extraHelp, optionType, declaringClass, field)); } private void createFiles(OptionsInfo info) { @@ -231,7 +231,7 @@ } private void createOptionsDescriptorsFile(OptionsInfo info, String pkg, Name topDeclaringClass, Element[] originatingElements) { - String optionsClassName = topDeclaringClass + "_" + OptionDescriptors.class.getSimpleName(); + String optionsClassName = topDeclaringClass + "_" + getSimpleName(OPTION_DESCRIPTORS_CLASS_NAME); Filer filer = processingEnv.getFiler(); try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) { @@ -243,12 +243,12 @@ out.println("package " + pkg + ";"); out.println(""); out.println("import java.util.*;"); - out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;"); - out.println("import " + OptionType.class.getName() + ";"); + out.println("import " + getPackageName(OPTION_DESCRIPTORS_CLASS_NAME) + ".*;"); + out.println("import " + OPTION_TYPE_CLASS_NAME + ";"); out.println(""); - out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {"); + out.println("public class " + optionsClassName + " implements " + getSimpleName(OPTION_DESCRIPTORS_CLASS_NAME) + " {"); - String desc = OptionDescriptor.class.getSimpleName(); + String desc = getSimpleName(OPTION_DESCRIPTOR_CLASS_NAME); Collections.sort(info.options); @@ -265,18 +265,18 @@ optionField = option.declaringClass + "." + option.field.getSimpleName(); } out.println(" case \"" + name + "\": {"); - OptionType optionType = option.optionType; + String optionType = option.optionType; String type = option.type; String help = option.help; - String[] extraHelp = option.extraHelp; + List extraHelp = option.extraHelp; String declaringClass = option.declaringClass; Name fieldName = option.field.getSimpleName(); out.printf(" return " + desc + ".create(\n"); out.printf(" /*name*/ \"%s\",\n", name); - out.printf(" /*optionType*/ %s.%s,\n", optionType.getDeclaringClass().getSimpleName(), optionType.name()); + out.printf(" /*optionType*/ %s.%s,\n", getSimpleName(OPTION_TYPE_CLASS_NAME), optionType); out.printf(" /*optionValueType*/ %s.class,\n", type); out.printf(" /*help*/ \"%s\",\n", help); - if (extraHelp.length != 0) { + if (extraHelp.size() != 0) { out.printf(" /*extraHelp*/ new String[] {\n"); for (String line : extraHelp) { out.printf(" \"%s\",\n", line.replace("\\", "\\\\").replace("\"", "\\\"")); @@ -336,14 +336,14 @@ static class OptionInfo implements Comparable { final String name; - final OptionType optionType; + final String optionType; final String help; - final String[] extraHelp; + final List extraHelp; final String type; final String declaringClass; final VariableElement field; - OptionInfo(String name, OptionType optionType, String help, String[] extraHelp, String type, String declaringClass, VariableElement field) { + OptionInfo(String name, String optionType, String help, List extraHelp, String type, String declaringClass, VariableElement field) { this.name = name; this.optionType = optionType; this.help = help; @@ -390,8 +390,13 @@ return true; } + TypeElement optionTypeElement = getTypeElement(OPTION_CLASS_NAME); + + optionTypeMirror = optionTypeElement.asType(); + optionKeyTypeMirror = getTypeElement(OPTION_KEY_CLASS_NAME).asType(); + Map map = new HashMap<>(); - for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) { + for (Element element : roundEnv.getElementsAnnotatedWith(optionTypeElement)) { if (!processed.contains(element)) { processed.add(element); Element topDeclaringType = topDeclaringType(element); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu May 31 13:39:26 2018 -0700 @@ -314,7 +314,7 @@ @SuppressWarnings("try") public boolean tryCanonicalize(final Node node, NodeClass nodeClass) { - try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.scope("tryCanonicalize", node)) { + try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) { if (customCanonicalizer != null) { Node canonical = customCanonicalizer.canonicalize(node); if (performReplacement(node, canonical)) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Thu May 31 13:39:26 2018 -0700 @@ -172,7 +172,8 @@ AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode; for (GuardNode guard : mergeNode.guards().snapshot()) { try (DebugCloseable closeable = guard.withNodeSourcePosition()) { - GuardNode newlyCreatedGuard = new GuardNode(guard.getCondition(), anchorBlock.getBeginNode(), guard.getReason(), guard.getAction(), guard.isNegated(), guard.getSpeculation()); + GuardNode newlyCreatedGuard = new GuardNode(guard.getCondition(), anchorBlock.getBeginNode(), guard.getReason(), guard.getAction(), guard.isNegated(), guard.getSpeculation(), + guard.getNoDeoptSuccessorPosition()); GuardNode newGuard = mergeNode.graph().unique(newlyCreatedGuard); guard.replaceAndDelete(newGuard); } @@ -205,7 +206,8 @@ continue; } try (DebugCloseable closeable = guard.withNodeSourcePosition()) { - GuardNode newlyCreatedGuard = new GuardNode(guard.getCondition(), anchorBlock.getBeginNode(), guard.getReason(), guard.getAction(), guard.isNegated(), speculation); + GuardNode newlyCreatedGuard = new GuardNode(guard.getCondition(), anchorBlock.getBeginNode(), guard.getReason(), guard.getAction(), guard.isNegated(), speculation, + guard.getNoDeoptSuccessorPosition()); GuardNode newGuard = node.graph().unique(newlyCreatedGuard); if (otherGuard.isAlive()) { otherGuard.replaceAndDelete(newGuard); @@ -245,7 +247,41 @@ } } - public static class Instance implements ControlFlowGraph.RecursiveVisitor { + public static final class Marks { + final int infoElementOperations; + final int conditions; + + public Marks(int infoElementOperations, int conditions) { + this.infoElementOperations = infoElementOperations; + this.conditions = conditions; + } + } + + protected static final class GuardedCondition { + private final GuardingNode guard; + private final LogicNode condition; + private final boolean negated; + + public GuardedCondition(GuardingNode guard, LogicNode condition, boolean negated) { + this.guard = guard; + this.condition = condition; + this.negated = negated; + } + + public GuardingNode getGuard() { + return guard; + } + + public LogicNode getCondition() { + return condition; + } + + public boolean isNegated() { + return negated; + } + } + + public static class Instance implements ControlFlowGraph.RecursiveVisitor { protected final NodeMap map; protected final BlockMap> blockToNodes; protected final NodeMap nodeToBlock; @@ -255,6 +291,8 @@ protected final DebugContext debug; protected final EconomicMap> mergeMaps; + protected final ArrayDeque conditions; + /** * Tests which may be eliminated because post dominating tests to prove a broader condition. */ @@ -267,7 +305,8 @@ this.nodeToBlock = nodeToBlock; this.undoOperations = new NodeStack(); this.map = graph.createNodeMap(); - pendingTests = new ArrayDeque<>(); + this.pendingTests = new ArrayDeque<>(); + this.conditions = new ArrayDeque<>(); tool = GraphUtil.getDefaultSimplifier(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), false, graph.getAssumptions(), graph.getOptions(), context.getLowerer()); mergeMaps = EconomicMap.create(); @@ -337,13 +376,14 @@ } @Override - public Integer enter(Block block) { - int mark = undoOperations.size(); + public Marks enter(Block block) { + int infoElementsMark = undoOperations.size(); + int conditionsMark = conditions.size(); debug.log("[Pre Processing block %s]", block); // For now conservatively collect guards only within the same block. pendingTests.clear(); processNodes(block); - return mark; + return new Marks(infoElementsMark, conditionsMark); } protected void processNodes(Block block) { @@ -531,8 +571,10 @@ UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) condition; ValueNode value = unaryLogicNode.getValue(); if (maybeMultipleUsages(value)) { + // getSucceedingStampForValue doesn't take the (potentially a Pi Node) input + // stamp into account, so it can be safely propagated. Stamp newStamp = unaryLogicNode.getSucceedingStampForValue(negated); - registerNewStamp(value, newStamp, guard); + registerNewStamp(value, newStamp, guard, true); } } else if (condition instanceof BinaryOpLogicNode) { BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) condition; @@ -753,17 +795,21 @@ } protected void registerCondition(LogicNode condition, boolean negated, GuardingNode guard) { - if (condition.getUsageCount() > 1) { + if (condition.hasMoreThanOneUsage()) { registerNewStamp(condition, negated ? StampFactory.contradiction() : StampFactory.tautology(), guard); } + conditions.push(new GuardedCondition(guard, condition, negated)); } protected InfoElement getInfoElements(ValueNode proxiedValue) { - ValueNode value = GraphUtil.skipPi(proxiedValue); - if (value == null) { + if (proxiedValue == null) { return null; } - return map.getAndGrow(value); + InfoElement infoElement = map.getAndGrow(proxiedValue); + if (infoElement == null) { + infoElement = map.getAndGrow(GraphUtil.skipPi(proxiedValue)); + } + return infoElement; } protected boolean rewireGuards(GuardingNode guard, boolean result, ValueNode proxifiedInput, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) { @@ -801,6 +847,13 @@ infoElement = nextElement(infoElement); } + for (GuardedCondition guardedCondition : this.conditions) { + TriState result = guardedCondition.getCondition().implies(guardedCondition.isNegated(), node); + if (result.isKnown()) { + return rewireGuards(guardedCondition.guard, result.toBoolean(), null, null, rewireGuardFunction); + } + } + if (node instanceof UnaryOpLogicNode) { UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) node; ValueNode value = unaryLogicNode.getValue(); @@ -943,30 +996,40 @@ } protected void registerNewStamp(ValueNode maybeProxiedValue, Stamp newStamp, GuardingNode guard) { + registerNewStamp(maybeProxiedValue, newStamp, guard, false); + } + + protected void registerNewStamp(ValueNode maybeProxiedValue, Stamp newStamp, GuardingNode guard, boolean propagateThroughPis) { assert maybeProxiedValue != null; assert guard != null; - if (newStamp != null) { - ValueNode value = maybeProxiedValue; - Stamp stamp = newStamp; + + if (newStamp == null || newStamp.isUnrestricted()) { + return; + } + + ValueNode value = maybeProxiedValue; + Stamp stamp = newStamp; + + while (stamp != null && value != null) { ValueNode proxiedValue = null; if (value instanceof PiNode) { proxiedValue = value; } - do { - counterStampsRegistered.increment(debug); - debug.log("\t Saving stamp for node %s stamp %s guarded by %s", value, stamp, guard); - assert value instanceof LogicNode || stamp.isCompatible(value.stamp(NodeView.DEFAULT)) : stamp + " vs. " + value.stamp(NodeView.DEFAULT) + " (" + value + ")"; - map.setAndGrow(value, new InfoElement(stamp, guard, proxiedValue, map.getAndGrow(value))); - undoOperations.push(value); - if (value instanceof StampInverter) { - StampInverter stampInverter = (StampInverter) value; - value = stampInverter.getValue(); - stamp = stampInverter.invertStamp(stamp); - } else { - value = null; - stamp = null; - } - } while (value != null && stamp != null); + counterStampsRegistered.increment(debug); + debug.log("\t Saving stamp for node %s stamp %s guarded by %s", value, stamp, guard); + assert value instanceof LogicNode || stamp.isCompatible(value.stamp(NodeView.DEFAULT)) : stamp + " vs. " + value.stamp(NodeView.DEFAULT) + " (" + value + ")"; + map.setAndGrow(value, new InfoElement(stamp, guard, proxiedValue, map.getAndGrow(value))); + undoOperations.push(value); + if (propagateThroughPis && value instanceof PiNode) { + PiNode piNode = (PiNode) value; + value = piNode.getOriginalNode(); + } else if (value instanceof StampInverter) { + StampInverter stampInverter = (StampInverter) value; + value = stampInverter.getValue(); + stamp = stampInverter.invertStamp(stamp); + } else { + break; + } } } @@ -990,7 +1053,9 @@ if (value.hasMoreThanOneUsage()) { return true; } else { - return value instanceof ProxyNode; + return value instanceof ProxyNode || + value instanceof PiNode || + value instanceof StampInverter; } } @@ -1019,14 +1084,19 @@ } @Override - public void exit(Block b, Integer state) { - int mark = state; - while (undoOperations.size() > mark) { + public void exit(Block b, Marks marks) { + int infoElementsMark = marks.infoElementOperations; + while (undoOperations.size() > infoElementsMark) { Node node = undoOperations.pop(); if (node.isAlive()) { map.set(node, map.get(node).getParent()); } } + + int conditionsMark = marks.conditions; + while (conditions.size() > conditionsMark) { + conditions.pop(); + } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Thu May 31 13:39:26 2018 -0700 @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -178,8 +179,9 @@ AbstractEndNode end = mergeNode.forwardEnds().first(); propagateFixed(end, deopt, loweringProvider); } - assert next.isAlive(); - propagateFixed(next, deopt, loweringProvider); + if (next.isAlive()) { + propagateFixed(next, deopt, loweringProvider); + } return; } else if (current.predecessor() instanceof IfNode) { IfNode ifNode = (IfNode) current.predecessor(); @@ -188,7 +190,9 @@ StructuredGraph graph = ifNode.graph(); LogicNode conditionNode = ifNode.condition(); boolean negateGuardCondition = current == ifNode.trueSuccessor(); - FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition)); + NodeSourcePosition survivingSuccessorPosition = negateGuardCondition ? ifNode.falseSuccessor().getNodeSourcePosition() : ifNode.trueSuccessor().getNodeSourcePosition(); + FixedGuardNode guard = graph.add( + new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition, survivingSuccessorPosition)); FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); AbstractBeginNode survivingSuccessor; @@ -223,11 +227,14 @@ } } + @SuppressWarnings("try") private static void moveAsDeoptAfter(FixedWithNextNode node, StaticDeoptimizingNode deopt) { - FixedNode next = node.next(); - if (next != deopt.asNode()) { - node.setNext(node.graph().add(new DeoptimizeNode(deopt.getAction(), deopt.getReason(), deopt.getSpeculation()))); - GraphUtil.killCFG(next); + try (DebugCloseable position = deopt.asNode().withNodeSourcePosition()) { + FixedNode next = node.next(); + if (next != deopt.asNode()) { + node.setNext(node.graph().add(new DeoptimizeNode(deopt.getAction(), deopt.getReason(), deopt.getSpeculation()))); + GraphUtil.killCFG(next); + } } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java Thu May 31 13:39:26 2018 -0700 @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.nodes.AbstractDeoptimizeNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.DynamicDeoptimizeNode; @@ -52,6 +53,7 @@ public class DeoptimizationGroupingPhase extends BasePhase { @Override + @SuppressWarnings("try") protected void run(StructuredGraph graph, MidTierContext context) { ControlFlowGraph cfg = null; for (FrameState fs : graph.getNodes(FrameState.TYPE)) { @@ -80,8 +82,9 @@ target.replaceAtPredecessor(firstEnd); exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg); - - merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi))); + try (DebugCloseable position = target.withNodeSourcePosition()) { + merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi))); + } obsoletes = new LinkedList<>(); obsoletes.add((AbstractDeoptimizeNode) target); target = merge; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java Thu May 31 13:39:26 2018 -0700 @@ -107,64 +107,66 @@ binary.safeDelete(); } - @SuppressWarnings("try") private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) { - try (DebugCloseable context = ifNode.withNodeSourcePosition()) { - /* - * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into - * two separate IfNodes: if(X) and if(Y) - * - * for computing the probabilities P(X) and P(Y), we use two different approaches. The - * first one assumes that the shortCircuitProbability and the probability on the IfNode - * were created with each other in mind. If this assumption does not hold, we fall back - * to another mechanism for computing the probabilities. - */ - AbstractBeginNode trueTarget = ifNode.trueSuccessor(); - AbstractBeginNode falseTarget = ifNode.falseSuccessor(); + /* + * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into two + * separate IfNodes: if(X) and if(Y) + * + * for computing the probabilities P(X) and P(Y), we use two different approaches. The first + * one assumes that the shortCircuitProbability and the probability on the IfNode were + * created with each other in mind. If this assumption does not hold, we fall back to + * another mechanism for computing the probabilities. + */ + AbstractBeginNode trueTarget = ifNode.trueSuccessor(); + AbstractBeginNode falseTarget = ifNode.falseSuccessor(); - // 1st approach - // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y)) - double firstIfTrueProbability = shortCircuitProbability; - double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability)); - double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability; + // 1st approach + // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y)) + double firstIfTrueProbability = shortCircuitProbability; + double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability)); + double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability; - if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) { - /* - * 2nd approach - * - * the assumption above did not hold, so we either used an artificial probability as - * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode. - * - * so, we distribute the if's trueSuccessorProbability between the newly generated - * if nodes according to the shortCircuitProbability. the following invariant is - * always true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * - * P(Y)) - */ - firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability; - secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability))); - } + if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) { + /* + * 2nd approach + * + * the assumption above did not hold, so we either used an artificial probability as + * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode. + * + * so, we distribute the if's trueSuccessorProbability between the newly generated if + * nodes according to the shortCircuitProbability. the following invariant is always + * true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y)) + */ + firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability; + secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability))); + } - ifNode.clearSuccessors(); - Graph graph = ifNode.graph(); - AbstractMergeNode trueTargetMerge = graph.add(new MergeNode()); - trueTargetMerge.setNext(trueTarget); - EndNode firstTrueEnd = graph.add(new EndNode()); - EndNode secondTrueEnd = graph.add(new EndNode()); - trueTargetMerge.addForwardEnd(firstTrueEnd); - trueTargetMerge.addForwardEnd(secondTrueEnd); - AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd); - AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd); - if (yNegated) { - secondIfTrueProbability = 1.0 - secondIfTrueProbability; - } - if (xNegated) { - firstIfTrueProbability = 1.0 - firstIfTrueProbability; - } - AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability))); - IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability)); - ifNode.replaceAtPredecessor(firstIf); - ifNode.safeDelete(); + ifNode.clearSuccessors(); + Graph graph = ifNode.graph(); + AbstractMergeNode trueTargetMerge = graph.add(new MergeNode()); + trueTargetMerge.setNext(trueTarget); + EndNode firstTrueEnd = graph.add(new EndNode()); + EndNode secondTrueEnd = graph.add(new EndNode()); + trueTargetMerge.addForwardEnd(firstTrueEnd); + trueTargetMerge.addForwardEnd(secondTrueEnd); + AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd); + firstTrueTarget.setNodeSourcePosition(trueTarget.getNodeSourcePosition()); + AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd); + secondTrueTarget.setNodeSourcePosition(trueTarget.getNodeSourcePosition()); + if (yNegated) { + secondIfTrueProbability = 1.0 - secondIfTrueProbability; } + if (xNegated) { + firstIfTrueProbability = 1.0 - firstIfTrueProbability; + } + IfNode secondIf = new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability); + secondIf.setNodeSourcePosition(ifNode.getNodeSourcePosition()); + AbstractBeginNode secondIfBegin = BeginNode.begin(graph.add(secondIf)); + secondIfBegin.setNodeSourcePosition(falseTarget.getNodeSourcePosition()); + IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIfBegin : firstTrueTarget, xNegated ? firstTrueTarget : secondIfBegin, firstIfTrueProbability)); + firstIf.setNodeSourcePosition(ifNode.getNodeSourcePosition()); + ifNode.replaceAtPredecessor(firstIf); + ifNode.safeDelete(); } private static boolean doubleEquals(double a, double b) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Thu May 31 13:39:26 2018 -0700 @@ -86,6 +86,7 @@ try (DebugCloseable position = guard.withNodeSourcePosition()) { StructuredGraph graph = guard.graph(); AbstractBeginNode fastPath = graph.add(new BeginNode()); + fastPath.setNodeSourcePosition(guard.getNoDeoptSuccessorPosition()); @SuppressWarnings("deprecation") int debugId = useGuardIdAsDebugId ? guard.getId() : DeoptimizeNode.DEFAULT_DEBUG_ID; DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.getAction(), guard.getReason(), debugId, guard.getSpeculation(), null)); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoopSafepointInsertionPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoopSafepointInsertionPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoopSafepointInsertionPhase.java Thu May 31 13:39:26 2018 -0700 @@ -24,6 +24,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.GenLoopSafepoints; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.SafepointNode; @@ -43,13 +44,16 @@ } @Override + @SuppressWarnings("try") protected void run(StructuredGraph graph) { if (GenLoopSafepoints.getValue(graph.getOptions())) { for (LoopBeginNode loopBeginNode : graph.getNodes(LoopBeginNode.TYPE)) { for (LoopEndNode loopEndNode : loopBeginNode.loopEnds()) { if (loopEndNode.canSafepoint()) { - SafepointNode safepointNode = graph.add(new SafepointNode()); - graph.addBeforeFixed(loopEndNode, safepointNode); + try (DebugCloseable s = loopEndNode.withNodeSourcePosition()) { + SafepointNode safepointNode = graph.add(new SafepointNode()); + graph.addBeforeFixed(loopEndNode, safepointNode); + } } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Thu May 31 13:39:26 2018 -0700 @@ -43,6 +43,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -171,7 +172,7 @@ @Override public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { - return createGuard(before, condition, deoptReason, action, JavaConstant.NULL_POINTER, false); + return createGuard(before, condition, deoptReason, action, JavaConstant.NULL_POINTER, false, null); } @Override @@ -180,7 +181,8 @@ } @Override - public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated) { + public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated, + NodeSourcePosition noDeoptSucccessorPosition) { StructuredGraph graph = before.graph(); if (OptEliminateGuards.getValue(graph.getOptions())) { for (Node usage : condition.usages()) { @@ -190,7 +192,7 @@ } } if (!condition.graph().getGuardsStage().allowsFloatingGuards()) { - FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, deoptReason, action, speculation, negated)); + FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, deoptReason, action, speculation, negated, noDeoptSucccessorPosition)); graph.addBeforeFixed(before, fixedGuard); DummyGuardHandle handle = graph.add(new DummyGuardHandle(fixedGuard)); fixedGuard.lower(this); @@ -198,7 +200,7 @@ handle.safeDelete(); return result; } else { - GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, speculation)); + GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, speculation, noDeoptSucccessorPosition)); if (OptEliminateGuards.getValue(graph.getOptions())) { activeGuards.markAndGrow(newGuard); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Thu May 31 13:39:26 2018 -0700 @@ -65,6 +65,7 @@ import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.nodes.DeoptimizingGuard; import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FixedNode; @@ -520,6 +521,7 @@ return listener.getNodes(); } + @SuppressWarnings("try") private static ValueNode finishInlining(Invoke invoke, StructuredGraph graph, FixedNode firstNode, List returnNodes, UnwindNode unwindNode, Assumptions inlinedAssumptions, StructuredGraph inlineGraph) { FixedNode invokeNode = invoke.asNode(); @@ -548,15 +550,19 @@ // get rid of memory kill AbstractBeginNode begin = invokeWithException.next(); if (begin instanceof KillingBeginNode) { - AbstractBeginNode newBegin = new BeginNode(); - graph.addAfterFixed(begin, graph.add(newBegin)); - begin.replaceAtUsages(newBegin); - graph.removeFixed(begin); + try (DebugCloseable position = begin.withNodeSourcePosition()) { + AbstractBeginNode newBegin = new BeginNode(); + graph.addAfterFixed(begin, graph.add(newBegin)); + begin.replaceAtUsages(newBegin); + graph.removeFixed(begin); + } } } else { if (unwindNode != null && unwindNode.isAlive()) { - DeoptimizeNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); - unwindNode.replaceAndDelete(deoptimizeNode); + try (DebugCloseable position = unwindNode.withNodeSourcePosition()) { + DeoptimizeNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); + unwindNode.replaceAndDelete(deoptimizeNode); + } } } @@ -710,6 +716,10 @@ posMap.put(pos, callerPos); } value.setNodeSourcePosition(callerPos); + + if (value instanceof DeoptimizingGuard) { + ((DeoptimizingGuard) value).addCallerToNoDeoptSuccessorPosition(callerPos.getCaller()); + } } else { if (isSubstitution) { /* @@ -721,7 +731,7 @@ } } } - assert invokeGraph.verifySourcePositions(); + assert invokeGraph.verifySourcePositions(false); } public static void processMonitorId(FrameState stateAfter, MonitorIdNode monitorIdNode) { @@ -871,6 +881,7 @@ return frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !frameState.getMethod().isSynchronized()); } + @SuppressWarnings("try") public static FrameState handleMissingAfterExceptionFrameState(FrameState nonReplaceableFrameState, Invoke invoke, EconomicMap replacements, boolean alwaysDuplicateStateAfter) { StructuredGraph graph = nonReplaceableFrameState.graph(); NodeWorkList workList = graph.createNodeWorkList(); @@ -890,9 +901,11 @@ AbstractMergeNode merge = (AbstractMergeNode) fixedStateSplit; while (merge.isAlive()) { AbstractEndNode end = merge.forwardEnds().first(); - DeoptimizeNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); - end.replaceAtPredecessor(deoptimizeNode); - GraphUtil.killCFG(end); + try (DebugCloseable position = end.withNodeSourcePosition()) { + DeoptimizeNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); + end.replaceAtPredecessor(deoptimizeNode); + GraphUtil.killCFG(end); + } } } else if (fixedStateSplit instanceof ExceptionObjectNode) { // The target invoke does not have an exception edge. This means that the @@ -909,12 +922,14 @@ } handleAfterBciFrameState(newInvoke.stateAfter(), invoke, alwaysDuplicateStateAfter); } else { - FixedNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); - if (fixedStateSplit instanceof AbstractBeginNode) { - deoptimizeNode = BeginNode.begin(deoptimizeNode); + try (DebugCloseable position = fixedStateSplit.withNodeSourcePosition()) { + FixedNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); + if (fixedStateSplit instanceof AbstractBeginNode) { + deoptimizeNode = BeginNode.begin(deoptimizeNode); + } + fixedStateSplit.replaceAtPredecessor(deoptimizeNode); + GraphUtil.killCFG(fixedStateSplit); } - fixedStateSplit.replaceAtPredecessor(deoptimizeNode); - GraphUtil.killCFG(fixedStateSplit); } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Thu May 31 13:39:26 2018 -0700 @@ -111,7 +111,14 @@ SnippetReflectionProvider snippetReflection = getSnippetReflectionProvider(); if (snippetReflection != null) { if (constant.getJavaKind() == JavaKind.Object) { - Object obj = snippetReflection.asObject(Object.class, constant); + Object obj = null; + /* + * Ignore any exceptions on unknown JavaConstant implementations in debugging code. + */ + try { + obj = snippetReflection.asObject(Object.class, constant); + } catch (Throwable ex) { + } if (obj != null) { return GraphPrinter.constantToString(obj); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.processor/src/org/graalvm/compiler/processor/AbstractProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.processor/src/org/graalvm/compiler/processor/AbstractProcessor.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.processor; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.processing.FilerException; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.tools.Diagnostic.Kind; +import javax.tools.FileObject; +import javax.tools.StandardLocation; + +/** + * {@link javax.annotation.processing.AbstractProcessor} subclass that provides extra functionality. + */ +@SuppressFBWarnings(value = "NM_SAME_SIMPLE_NAME_AS_SUPERCLASS", // + reason = "We want this type to be found when someone is writing a new Graal annotation processor") +public abstract class AbstractProcessor extends javax.annotation.processing.AbstractProcessor { + + /** + * Gets the processing environment available to this processor. + */ + public ProcessingEnvironment env() { + return processingEnv; + } + + private final Map types = new HashMap<>(); + + /** + * Gets the {@link TypeMirror} for a given class name. + * + * @throws NoClassDefFoundError if the class cannot be resolved + */ + public TypeMirror getType(String className) { + return getTypeElement(className).asType(); + } + + /** + * Gets the {@link TypeMirror} for a given class name. + * + * @rturn {@code null} if the class cannot be resolved + */ + public TypeMirror getTypeOrNull(String className) { + TypeElement element = getTypeElementOrNull(className); + if (element == null) { + return null; + } + return element.asType(); + } + + /** + * Gets the {@link TypeElement} for a given class name. + * + * @throws NoClassDefFoundError if the class cannot be resolved + */ + public TypeElement getTypeElement(String className) { + TypeElement type = getTypeElementOrNull(className); + if (type == null) { + throw new NoClassDefFoundError(className); + } + return type; + } + + /** + * Gets the {@link TypeElement} for a given class name. + * + * @returns {@code null} if the class cannot be resolved + */ + public TypeElement getTypeElementOrNull(String className) { + TypeElement type = types.get(className); + if (type == null) { + type = processingEnv.getElementUtils().getTypeElement(className); + if (type == null) { + return null; + } + types.put(className, type); + } + return type; + } + + /** + * Converts a given {@link TypeMirror} to a {@link TypeElement}. + * + * @throws ClassCastException if type cannot be converted to a {@link TypeElement} + */ + public TypeElement asTypeElement(TypeMirror type) { + Element element = processingEnv.getTypeUtils().asElement(type); + if (element == null) { + throw new ClassCastException(type + " cannot be converted to a " + TypeElement.class.getName()); + } + return (TypeElement) element; + } + + /** + * Regular expression for a qualified class name that assumes package names start with lowercase + * and non-package components start with uppercase. + */ + private static final Pattern QUALIFIED_CLASS_NAME_RE = Pattern.compile("(?:[a-z]\\w*\\.)+([A-Z].*)"); + + /** + * Gets the non-package component of a qualified class name. + * + * @throws IllegalArgumentException if {@code className} does not match + * {@link #QUALIFIED_CLASS_NAME_RE} + */ + public static String getSimpleName(String className) { + Matcher m = QUALIFIED_CLASS_NAME_RE.matcher(className); + if (m.matches()) { + return m.group(1); + } + throw new IllegalArgumentException("Class name \"" + className + "\" does not match pattern " + QUALIFIED_CLASS_NAME_RE); + } + + /** + * Gets the package component of a qualified class name. + * + * @throws IllegalArgumentException if {@code className} does not match + * {@link #QUALIFIED_CLASS_NAME_RE} + */ + public static String getPackageName(String className) { + String simpleName = getSimpleName(className); + return className.substring(0, className.length() - simpleName.length() - 1); + } + + /** + * Gets the annotation of type {@code annotationType} directly present on {@code element}. + * + * @return {@code null} if an annotation of type {@code annotationType} is not on + * {@code element} + */ + public AnnotationMirror getAnnotation(Element element, TypeMirror annotationType) { + List mirrors = getAnnotations(element, annotationType); + return mirrors.isEmpty() ? null : mirrors.get(0); + } + + /** + * Gets all annotations directly present on {@code element}. + */ + public List getAnnotations(Element element, TypeMirror typeMirror) { + List result = new ArrayList<>(); + for (AnnotationMirror mirror : element.getAnnotationMirrors()) { + if (processingEnv.getTypeUtils().isSameType(mirror.getAnnotationType(), typeMirror)) { + result.add(mirror); + } + } + return result; + } + + /** + * Gets the value of the {@code name} element of {@code annotation} and converts it to a value + * of type {@code type}. + * + * @param type the expected type of the element value. This must be a subclass of one of the + * types described by {@link AnnotationValue}. + * @throws NoSuchElementException if {@code annotation} has no element named {@code name} + * @throws ClassCastException if the value of the specified element cannot be converted to + * {@code type} + */ + public static T getAnnotationValue(AnnotationMirror annotation, String name, Class type) { + ExecutableElement valueMethod = null; + for (ExecutableElement method : ElementFilter.methodsIn(annotation.getAnnotationType().asElement().getEnclosedElements())) { + if (method.getSimpleName().toString().equals(name)) { + valueMethod = method; + break; + } + } + + if (valueMethod == null) { + return null; + } + + AnnotationValue value = annotation.getElementValues().get(valueMethod); + if (value == null) { + value = valueMethod.getDefaultValue(); + } + + return type.cast(value.getValue()); + } + + /** + * Gets the value of the {@code name} array-typed element of {@code annotation} and converts it + * to list of values of type {@code type}. + * + * @param componentType the expected component type of the element value. This must be a + * subclass of one of the types described by {@link AnnotationValue}. + * @throws NoSuchElementException if {@code annotation} has no element named {@code name} + * @throws ClassCastException if the value of the specified element is not an array whose + * components cannot be converted to {@code componentType} + */ + @SuppressWarnings("unchecked") + public static List getAnnotationValueList(AnnotationMirror annotation, String name, Class componentType) { + List values = getAnnotationValue(annotation, name, List.class); + List result = new ArrayList<>(); + + if (values != null) { + for (AnnotationValue value : values) { + result.add(componentType.cast(value.getValue())); + } + } + return result; + } + + /** + * Creates a {@code META-INF/providers/} file whose contents are a single + * line containing {@code serviceClassName}. + */ + public void createProviderFile(String providerClassName, String serviceClassName, Element... originatingElements) { + assert originatingElements.length > 0; + String filename = "META-INF/providers/" + providerClassName; + try { + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + writer.println(serviceClassName); + writer.close(); + } catch (IOException e) { + processingEnv.getMessager().printMessage(isBug367599(e) ? Kind.NOTE : Kind.ERROR, e.getMessage(), originatingElements[0]); + } + } + + /** + * Determines if a given exception is (most likely) caused by + * Bug 367599. + */ + private static boolean isBug367599(Throwable t) { + if (t instanceof FilerException) { + for (StackTraceElement ste : t.getStackTrace()) { + if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) { + // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599 + return true; + } + } + } + return t.getCause() != null && isBug367599(t.getCause()); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.processor/src/org/graalvm/compiler/processor/SuppressFBWarnings.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.processor/src/org/graalvm/compiler/processor/SuppressFBWarnings.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.processor; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Used to suppress FindBugs warnings. + */ +@Retention(RetentionPolicy.CLASS) +@interface SuppressFBWarnings { + /** + * The set of FindBugs + * warnings that are to be + * suppressed in annotated element. The value can be a bug category, kind or pattern. + */ + java.lang.String[] value(); + + String reason(); +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,20 +29,29 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; import static org.graalvm.compiler.serviceprovider.GraalServices.JAVA_SPECIFICATION_VERSION; +import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier; import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool.RoundingMode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.graalvm.compiler.nodes.java.AtomicReadAndAddNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; +import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; +import sun.misc.Unsafe; public class AArch64GraphBuilderPlugins { @@ -56,7 +65,11 @@ registerMathPlugins(invocationPlugins); registerStringLatin1Plugins(invocationPlugins, bytecodeProvider); registerStringUTF16Plugins(invocationPlugins, bytecodeProvider); - + registerUnsafeReadAndAddPlugins(invocationPlugins, bytecodeProvider); + // This is temporarily disabled until we implement correct emitting of the CAS + // instructions of the proper width. + StandardGraphBuilderPlugins.registerPlatformSpecificUnsafePlugins(invocationPlugins, bytecodeProvider, + new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}); } }); } @@ -107,6 +120,9 @@ return true; } }); + registerRound(r, "rint", RoundingMode.NEAREST); + registerRound(r, "ceil", RoundingMode.UP); + registerRound(r, "floor", RoundingMode.DOWN); } private static void registerUnaryMath(Registration r, String name, UnaryOperation operation) { @@ -119,6 +135,16 @@ }); } + private static void registerRound(Registration r, String name, RoundingMode mode) { + r.register1(name, Double.TYPE, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + b.push(JavaKind.Double, b.append(new AArch64RoundNode(arg, mode))); + return true; + } + }); + } + private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { if (JAVA_SPECIFICATION_VERSION >= 9) { Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider); @@ -137,4 +163,30 @@ } } + private static void registerUnsafeReadAndAddPlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { + Registration r; + if (Java8OrEarlier) { + r = new Registration(plugins, Unsafe.class); + } else { + r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementsBytecodeProvider); + } + + for (JavaKind kind : new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}) { + Class javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass(); + + if (kind != JavaKind.Object) { + r.register4("getAndAdd" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) { + // Emits a null-check for the otherwise unused receiver + unsafe.get(); + AddressNode address = b.add(new OffsetAddressNode(object, offset)); + b.addPush(kind, new AtomicReadAndAddNode(address, delta, kind, LocationIdentity.any())); + b.getGraph().markUnsafeAccess(); + return true; + } + }); + } + } + } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,6 @@ /* * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +25,9 @@ package org.graalvm.compiler.replacements.aarch64; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -34,7 +37,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FixedBinaryNode; +import org.graalvm.compiler.nodes.calc.IntegerDivRemNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; import org.graalvm.compiler.nodes.calc.SignedRemNode; import org.graalvm.compiler.nodes.calc.UnsignedDivNode; @@ -84,7 +87,7 @@ ulrem = snippet(AArch64IntegerArithmeticSnippets.class, "ulremSnippet"); } - public void lower(FixedBinaryNode node, LoweringTool tool) { + public void lower(IntegerDivRemNode node, LoweringTool tool) { JavaKind kind = node.stamp(NodeView.DEFAULT).getStackKind(); assert kind == JavaKind.Int || kind == JavaKind.Long; SnippetTemplate.SnippetInfo snippet; @@ -106,68 +109,88 @@ Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("x", node.getX()); args.add("y", node.getY()); + + IntegerStamp yStamp = (IntegerStamp) node.getY().stamp(NodeView.DEFAULT); + args.addConst("needsZeroCheck", node.getZeroCheck() == null && yStamp.contains(0)); + template(node, args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, args); } @Snippet - public static int idivSnippet(int x, int y) { - checkForZero(y); + public static int idivSnippet(int x, int y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeDiv(x, y); } @Snippet - public static long ldivSnippet(long x, long y) { - checkForZero(y); + public static long ldivSnippet(long x, long y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeDiv(x, y); } @Snippet - public static int iremSnippet(int x, int y) { - checkForZero(y); + public static int iremSnippet(int x, int y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeRem(x, y); } @Snippet - public static long lremSnippet(long x, long y) { - checkForZero(y); + public static long lremSnippet(long x, long y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeRem(x, y); } @Snippet - public static int uidivSnippet(int x, int y) { - checkForZero(y); + public static int uidivSnippet(int x, int y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeUDiv(x, y); } @Snippet - public static long uldivSnippet(long x, long y) { - checkForZero(y); + public static long uldivSnippet(long x, long y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeUDiv(x, y); } @Snippet - public static int uiremSnippet(int x, int y) { - checkForZero(y); + public static int uiremSnippet(int x, int y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeURem(x, y); } @Snippet - public static long ulremSnippet(long x, long y) { - checkForZero(y); + public static long ulremSnippet(long x, long y, @ConstantParameter boolean needsZeroCheck) { + if (needsZeroCheck) { + checkForZero(y); + } return safeURem(x, y); } private static void checkForZero(int y) { if (y == 0) { // "/ by zero" - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.ArithmeticException); + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException); } } private static void checkForZero(long y) { if (y == 0) { // "/ by zero" - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.ArithmeticException); + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException); } } @@ -207,7 +230,7 @@ public static final NodeClass TYPE = NodeClass.create(SafeSignedDivNode.class); protected SafeSignedDivNode(ValueNode x, ValueNode y) { - super(TYPE, x, y); + super(TYPE, x, y, null); } @Override @@ -223,7 +246,7 @@ public static final NodeClass TYPE = NodeClass.create(SafeSignedRemNode.class); protected SafeSignedRemNode(ValueNode x, ValueNode y) { - super(TYPE, x, y); + super(TYPE, x, y, null); } @Override @@ -239,7 +262,7 @@ public static final NodeClass TYPE = NodeClass.create(SafeUnsignedDivNode.class); protected SafeUnsignedDivNode(ValueNode x, ValueNode y) { - super(TYPE, x, y); + super(TYPE, x, y, null); } @Override @@ -255,7 +278,7 @@ public static final NodeClass TYPE = NodeClass.create(SafeUnsignedRemNode.class); protected SafeUnsignedRemNode(ValueNode x, ValueNode y) { - super(TYPE, x, y); + super(TYPE, x, y, null); } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64RoundNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64RoundNode.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.graalvm.compiler.replacements.aarch64; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import org.graalvm.compiler.core.common.type.FloatStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; +import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; +import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool; +import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool.RoundingMode; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.UnaryNode; +import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; + +/** + * Round floating-point value. + */ +@NodeInfo(cycles = CYCLES_8) +public final class AArch64RoundNode extends UnaryNode implements ArithmeticLIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AArch64RoundNode.class); + + private final RoundingMode mode; + + public AArch64RoundNode(ValueNode value, RoundingMode mode) { + super(TYPE, roundStamp((FloatStamp) value.stamp(NodeView.DEFAULT), mode), value); + this.mode = mode; + } + + private static double round(RoundingMode mode, double input) { + switch (mode) { + case DOWN: + return Math.floor(input); + case NEAREST: + return Math.rint(input); + case UP: + return Math.ceil(input); + case TRUNCATE: + return (long) input; + default: + throw GraalError.unimplemented("unimplemented RoundingMode " + mode); + } + } + + private static FloatStamp roundStamp(FloatStamp stamp, RoundingMode mode) { + double min = stamp.lowerBound(); + min = Math.min(min, round(mode, min)); + + double max = stamp.upperBound(); + max = Math.max(max, round(mode, max)); + + return new FloatStamp(stamp.getBits(), min, max, stamp.isNonNaN()); + } + + @Override + public Stamp foldStamp(Stamp newStamp) { + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); + return roundStamp((FloatStamp) newStamp, mode); + } + + private ValueNode tryFold(ValueNode input) { + if (input.isConstant()) { + JavaConstant c = input.asJavaConstant(); + if (c.getJavaKind() == JavaKind.Double) { + return ConstantNode.forDouble(round(mode, c.asDouble())); + } else if (c.getJavaKind() == JavaKind.Float) { + return ConstantNode.forFloat((float) round(mode, c.asFloat())); + } + } + return null; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode folded = tryFold(forValue); + return folded != null ? folded : this; + } + + @Override + public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) { + builder.setResult(this, ((AArch64ArithmeticLIRGeneratorTool) gen).emitRound(builder.operand(getValue()), mode)); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu May 31 13:39:26 2018 -0700 @@ -50,6 +50,7 @@ import org.graalvm.compiler.replacements.ArraysSubstitutions; import org.graalvm.compiler.replacements.IntegerSubstitutions; import org.graalvm.compiler.replacements.LongSubstitutions; +import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.UnsafeGetPlugin; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.UnsafePutPlugin; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; @@ -74,6 +75,8 @@ public void run() { registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, arch, replacementsBytecodeProvider); registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, arch, replacementsBytecodeProvider); + StandardGraphBuilderPlugins.registerPlatformSpecificUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, + new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double}); registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider); registerStringPlugins(invocationPlugins, arch, replacementsBytecodeProvider); registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider); @@ -218,12 +221,16 @@ private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { Registration r; + JavaKind[] unsafeJavaKinds; if (Java8OrEarlier) { r = new Registration(plugins, Unsafe.class); + unsafeJavaKinds = new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}; } else { r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementsBytecodeProvider); + unsafeJavaKinds = new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Object}; } - for (JavaKind kind : new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}) { + + for (JavaKind kind : unsafeJavaKinds) { Class javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass(); r.register4("getAndSet" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { @@ -236,14 +243,14 @@ return true; } }); - if (kind != JavaKind.Object) { + if (kind != JavaKind.Boolean && kind.isNumericInteger()) { r.register4("getAndAdd" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) { // Emits a null-check for the otherwise unused receiver unsafe.get(); AddressNode address = b.add(new OffsetAddressNode(object, offset)); - b.addPush(kind, new AtomicReadAndAddNode(address, delta, LocationIdentity.any())); + b.addPush(kind, new AtomicReadAndAddNode(address, delta, kind, LocationIdentity.any())); b.getGraph().markUnsafeAccess(); return true; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk9.test/src/org/graalvm/compiler/replacements/jdk9/UnsafeReplacementsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk9.test/src/org/graalvm/compiler/replacements/jdk9/UnsafeReplacementsTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.jdk9; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; +import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.test.AddExports; +import org.junit.Test; + +@AddExports("java.base/jdk.internal.misc") +public class UnsafeReplacementsTest extends MethodSubstitutionTest { + + // See GR-9819. + @SuppressWarnings("unused") ResolvedJavaMethod method = null; + + static class Container { + public volatile boolean booleanField; + public volatile byte byteField = 17; + public volatile char charField = 1025; + public volatile short shortField = 2232; + public volatile int intField = 0xcafebabe; + public volatile long longField = 0xdedababafafaL; + public volatile float floatField = 0.125f; + public volatile double doubleField = 0.125; + public volatile Object objectField = dummyValue; + } + + static jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); + static Container dummyValue = new Container(); + static Container newDummyValue = new Container(); + static long booleanOffset; + static long byteOffset; + static long charOffset; + static long shortOffset; + static long intOffset; + static long longOffset; + static long floatOffset; + static long doubleOffset; + static long objectOffset; + + static { + try { + booleanOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("booleanField")); + byteOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("byteField")); + charOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("charField")); + shortOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("shortField")); + intOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("intField")); + longOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("longField")); + floatOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("floatField")); + doubleOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("doubleField")); + objectOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("objectField")); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public static boolean unsafeCompareAndSetBoolean() { + Container container = new Container(); + return unsafe.compareAndSetBoolean(container, booleanOffset, false, true); + } + + public static boolean unsafeCompareAndSetByte() { + Container container = new Container(); + return unsafe.compareAndSetByte(container, byteOffset, (byte) 17, (byte) 121); + } + + public static boolean unsafeCompareAndSetChar() { + Container container = new Container(); + return unsafe.compareAndSetChar(container, charOffset, (char) 1025, (char) 1777); + } + + public static boolean unsafeCompareAndSetShort() { + Container container = new Container(); + return unsafe.compareAndSetShort(container, shortOffset, (short) 2232, (short) 12111); + } + + public static boolean unsafeCompareAndSetInt() { + Container container = new Container(); + return unsafe.compareAndSetInt(container, intOffset, 0xcafebabe, 0xbabefafa); + } + + public static boolean unsafeCompareAndSetLong() { + Container container = new Container(); + return unsafe.compareAndSetLong(container, longOffset, 0xdedababafafaL, 0xfafacecafafadedaL); + } + + public static boolean unsafeCompareAndSetFloat() { + Container container = new Container(); + return unsafe.compareAndSetFloat(container, floatOffset, 0.125f, 0.25f); + } + + public static boolean unsafeCompareAndSetDouble() { + Container container = new Container(); + return unsafe.compareAndSetDouble(container, doubleOffset, 0.125, 0.25); + } + + public static boolean unsafeCompareAndSetObject() { + Container container = new Container(); + return unsafe.compareAndSetObject(container, objectOffset, dummyValue, newDummyValue); + } + + public static boolean unsafeCompareAndExchangeBoolean() { + Container container = new Container(); + return unsafe.compareAndExchangeBoolean(container, booleanOffset, false, true); + } + + public static byte unsafeCompareAndExchangeByte() { + Container container = new Container(); + return unsafe.compareAndExchangeByte(container, byteOffset, (byte) 17, (byte) 31); + } + + public static char unsafeCompareAndExchangeChar() { + Container container = new Container(); + return unsafe.compareAndExchangeChar(container, charOffset, (char) 1025, (char) 4502); + } + + public static short unsafeCompareAndExchangeShort() { + Container container = new Container(); + return unsafe.compareAndExchangeShort(container, shortOffset, (short) 2232, (short) 8121); + } + + public static int unsafeCompareAndExchangeInt() { + Container container = new Container(); + return unsafe.compareAndExchangeInt(container, intOffset, 0xcafebabe, 0xbabefafa); + } + + public static long unsafeCompareAndExchangeLong() { + Container container = new Container(); + return unsafe.compareAndExchangeLong(container, longOffset, 0xdedababafafaL, 0xfafacecafafadedaL); + } + + public static float unsafeCompareAndExchangeFloat() { + Container container = new Container(); + return unsafe.compareAndExchangeFloat(container, floatOffset, 0.125f, 0.25f); + } + + public static double unsafeCompareAndExchangeDouble() { + Container container = new Container(); + return unsafe.compareAndExchangeDouble(container, doubleOffset, 0.125, 0.25); + } + + public static Object unsafeCompareAndExchangeObject() { + Container container = new Container(); + return unsafe.compareAndExchangeObject(container, objectOffset, dummyValue, newDummyValue); + } + + @Test + public void testCompareAndSet() { + TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget(); + if (target.arch instanceof AMD64) { + testGraph("unsafeCompareAndSetBoolean"); + testGraph("unsafeCompareAndSetByte"); + testGraph("unsafeCompareAndSetChar"); + testGraph("unsafeCompareAndSetShort"); + testGraph("unsafeCompareAndSetInt"); + testGraph("unsafeCompareAndSetLong"); + testGraph("unsafeCompareAndSetFloat"); + testGraph("unsafeCompareAndSetDouble"); + testGraph("unsafeCompareAndSetObject"); + testGraph("unsafeCompareAndExchangeBoolean"); + testGraph("unsafeCompareAndExchangeByte"); + testGraph("unsafeCompareAndExchangeChar"); + testGraph("unsafeCompareAndExchangeShort"); + testGraph("unsafeCompareAndExchangeInt"); + testGraph("unsafeCompareAndExchangeLong"); + testGraph("unsafeCompareAndExchangeFloat"); + testGraph("unsafeCompareAndExchangeDouble"); + testGraph("unsafeCompareAndExchangeObject"); + } + test("unsafeCompareAndSetBoolean"); + test("unsafeCompareAndSetByte"); + test("unsafeCompareAndSetChar"); + test("unsafeCompareAndSetShort"); + test("unsafeCompareAndSetInt"); + test("unsafeCompareAndSetLong"); + test("unsafeCompareAndSetFloat"); + test("unsafeCompareAndSetDouble"); + test("unsafeCompareAndSetObject"); + test("unsafeCompareAndExchangeBoolean"); + test("unsafeCompareAndExchangeByte"); + test("unsafeCompareAndExchangeChar"); + test("unsafeCompareAndExchangeShort"); + test("unsafeCompareAndExchangeInt"); + test("unsafeCompareAndExchangeLong"); + test("unsafeCompareAndExchangeFloat"); + test("unsafeCompareAndExchangeDouble"); + test("unsafeCompareAndExchangeObject"); + } + + public static int unsafeGetAndAddByte() { + Container container = new Container(); + return unsafe.getAndAddByte(container, byteOffset, (byte) 2); + } + + public static int unsafeGetAndAddChar() { + Container container = new Container(); + return unsafe.getAndAddChar(container, charOffset, (char) 250); + } + + public static int unsafeGetAndAddShort() { + Container container = new Container(); + return unsafe.getAndAddShort(container, shortOffset, (short) 1250); + } + + public static int unsafeGetAndAddInt() { + Container container = new Container(); + return unsafe.getAndAddInt(container, intOffset, 104501); + } + + public static long unsafeGetAndAddLong() { + Container container = new Container(); + return unsafe.getAndAddLong(container, longOffset, 0x123456abcdL); + } + + @Test + public void testGetAndAdd() { + TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget(); + if (target.arch instanceof AMD64) { + testGraph("unsafeGetAndAddByte"); + testGraph("unsafeGetAndAddChar"); + testGraph("unsafeGetAndAddShort"); + testGraph("unsafeGetAndAddInt"); + testGraph("unsafeGetAndAddLong"); + } + test("unsafeGetAndAddByte"); + test("unsafeGetAndAddChar"); + test("unsafeGetAndAddShort"); + test("unsafeGetAndAddInt"); + test("unsafeGetAndAddLong"); + } + + public static boolean unsafeGetAndSetBoolean() { + Container container = new Container(); + return unsafe.getAndSetBoolean(container, booleanOffset, true); + } + + public static byte unsafeGetAndSetByte() { + Container container = new Container(); + return unsafe.getAndSetByte(container, byteOffset, (byte) 129); + } + + public static char unsafeGetAndSetChar() { + Container container = new Container(); + return unsafe.getAndSetChar(container, charOffset, (char) 21111); + } + + public static short unsafeGetAndSetShort() { + Container container = new Container(); + return unsafe.getAndSetShort(container, shortOffset, (short) 21111); + } + + public static int unsafeGetAndSetInt() { + Container container = new Container(); + return unsafe.getAndSetInt(container, intOffset, 0x1234af); + } + + public static long unsafeGetAndSetLong() { + Container container = new Container(); + return unsafe.getAndSetLong(container, longOffset, 0x12345678abL); + } + + public static Object unsafeGetAndSetObject() { + Container container = new Container(); + container.objectField = null; + Container other = new Container(); + return unsafe.getAndSetObject(container, objectOffset, other); + } + + @Test + public void testGetAndSet() { + TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget(); + if (target.arch instanceof AMD64) { + testGraph("unsafeGetAndSetBoolean"); + testGraph("unsafeGetAndSetByte"); + testGraph("unsafeGetAndSetChar"); + testGraph("unsafeGetAndSetShort"); + testGraph("unsafeGetAndSetInt"); + testGraph("unsafeGetAndSetLong"); + testGraph("unsafeGetAndSetObject"); + } + test("unsafeGetAndSetBoolean"); + test("unsafeGetAndSetByte"); + test("unsafeGetAndSetChar"); + test("unsafeGetAndSetShort"); + test("unsafeGetAndSetInt"); + test("unsafeGetAndSetLong"); + test("unsafeGetAndSetObject"); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/META-INF/services/javax.annotation.processing.Processor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/META-INF/services/javax.annotation.processing.Processor Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,1 @@ +org.graalvm.compiler.replacements.processor.ReplacementsAnnotationProcessor diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/APHotSpotSignature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/APHotSpotSignature.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; + +/** + * Pretty much copied from HotSpotSignature but using a different method for resolving types. This + * class should be rewritten, its just a quick hack to get signatures working. + */ +final class APHotSpotSignature { + + private final List arguments = new ArrayList<>(); + private final String returnType; + private final String originalString; + private TypeMirror[] argumentTypes; + private TypeMirror returnTypeCache; + + APHotSpotSignature(String signature) { + assert signature.length() > 0; + this.originalString = signature; + + if (signature.charAt(0) == '(') { + int cur = 1; + while (cur < signature.length() && signature.charAt(cur) != ')') { + int nextCur = parseSignature(signature, cur); + arguments.add(signature.substring(cur, nextCur)); + cur = nextCur; + } + + cur++; + int nextCur = parseSignature(signature, cur); + returnType = signature.substring(cur, nextCur); + if (nextCur != signature.length()) { + throw new RuntimeException("Invalid trailing characters."); + } + } else { + returnType = null; + } + } + + private static int parseSignature(String signature, int start) { + int cur = start; + char first; + do { + first = signature.charAt(cur++); + } while (first == '['); + + switch (first) { + case 'L': + while (signature.charAt(cur) != ';') { + cur++; + } + cur++; + break; + case 'V': + case 'I': + case 'B': + case 'C': + case 'D': + case 'F': + case 'J': + case 'S': + case 'Z': + break; + default: + throw new RuntimeException("Invalid character at index " + cur + " in signature: " + signature); + } + return cur; + } + + public int getParameterCount(boolean withReceiver) { + return arguments.size() + (withReceiver ? 1 : 0); + } + + public TypeMirror getParameterType(ProcessingEnvironment env, int index) { + if (argumentTypes == null) { + argumentTypes = new TypeMirror[arguments.size()]; + } + TypeMirror type = argumentTypes[index]; + if (arguments.get(index) == null) { + throw new RuntimeException(String.format("Invalid argument at index %s.", index)); + } + + if (type == null) { + argumentTypes[index] = lookupType(env, arguments.get(index)); + } + return argumentTypes[index]; + } + + private static TypeMirror lookupType(ProcessingEnvironment env, String binaryName) { + if (binaryName.length() == 1) { + TypeKind kind = fromPrimitiveOrVoidTypeChar(binaryName.charAt(0)); + if (kind.isPrimitive()) { + return env.getTypeUtils().getPrimitiveType(kind); + } else if (kind == TypeKind.VOID) { + return env.getTypeUtils().getNoType(kind); + } + } + + String canonicalName = binaryName; + if (canonicalName.startsWith("L") && canonicalName.endsWith(";")) { + canonicalName = canonicalName.substring(1, canonicalName.length() - 1); + } + env.getMessager().printMessage(Kind.ERROR, canonicalName); + + int arrayDims = 0; + while (canonicalName.startsWith("[")) { + canonicalName = canonicalName.substring(1, canonicalName.length()); + arrayDims++; + } + + canonicalName = canonicalName.replaceAll("/", "."); + TypeElement typeElement = env.getElementUtils().getTypeElement(canonicalName); + if (typeElement == null) { + throw new RuntimeException(String.format("Type with name %s not found.", canonicalName)); + } + TypeMirror mirror = typeElement.asType(); + for (int i = 0; i < arrayDims; i++) { + mirror = env.getTypeUtils().getArrayType(mirror); + } + return mirror; + } + + /** + * Returns the kind from the character describing a primitive or void. + * + * @param ch the character + * @return the kind + */ + public static TypeKind fromPrimitiveOrVoidTypeChar(char ch) { + switch (ch) { + case 'Z': + return TypeKind.BOOLEAN; + case 'C': + return TypeKind.CHAR; + case 'F': + return TypeKind.FLOAT; + case 'D': + return TypeKind.DOUBLE; + case 'B': + return TypeKind.BYTE; + case 'S': + return TypeKind.SHORT; + case 'I': + return TypeKind.INT; + case 'J': + return TypeKind.LONG; + case 'V': + return TypeKind.VOID; + } + throw new IllegalArgumentException("unknown primitive or void type character: " + ch); + } + + public TypeMirror getReturnType(ProcessingEnvironment env) { + if (returnTypeCache == null) { + if (returnType == null) { + throw new RuntimeException("Invalid return type."); + } + returnTypeCache = lookupType(env, returnType); + } + return returnTypeCache; + } + + @Override + public String toString() { + return "Signature<" + originalString + ">"; + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/AnnotationHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/AnnotationHandler.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Handles processing of a single annotation type. + */ +public abstract class AnnotationHandler { + + protected final AbstractProcessor processor; + protected final String annotationTypeName; + + public AnnotationHandler(AbstractProcessor processor, String annotationTypeName) { + this.processor = processor; + this.annotationTypeName = annotationTypeName; + } + + /** + * Processes the presence of {@code annotation} on {@code element}. + */ + public abstract void process(Element element, AnnotationMirror annotation, PluginGenerator generator); +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ClassSubstitutionHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ClassSubstitutionHandler.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValue; +import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValueList; + +import java.util.List; + +import javax.annotation.processing.Messager; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Handler for the {@value #CLASS_SUBSTITUTION_CLASS_NAME} annotation. + */ +public final class ClassSubstitutionHandler extends AnnotationHandler { + + static final String CLASS_SUBSTITUTION_CLASS_NAME = "org.graalvm.compiler.api.replacements.ClassSubstitution"; + + public ClassSubstitutionHandler(AbstractProcessor env) { + super(env, CLASS_SUBSTITUTION_CLASS_NAME); + } + + @Override + public void process(Element element, AnnotationMirror classSubstitution, PluginGenerator generator) { + if (!element.getKind().isClass()) { + assert false : "Element is guaranteed to be a class."; + return; + } + TypeElement type = (TypeElement) element; + + TypeElement substitutionType = resolveOriginalType(processor, type, classSubstitution); + if (substitutionType == null) { + return; + } + } + + static TypeElement resolveOriginalType(AbstractProcessor processor, Element sourceElement, AnnotationMirror classSubstition) { + TypeMirror type = getAnnotationValue(classSubstition, "value", TypeMirror.class); + List classNames = getAnnotationValueList(classSubstition, "className", String.class); + boolean optional = getAnnotationValue(classSubstition, "optional", Boolean.class); + + Messager messager = processor.env().getMessager(); + if (type.getKind() != TypeKind.DECLARED) { + messager.printMessage(Kind.ERROR, "The provided class must be a declared type.", sourceElement, classSubstition); + return null; + } + + if (!classSubstition.getAnnotationType().asElement().equals(((DeclaredType) type).asElement())) { + if (classNames.size() != 0) { + String msg = "The usage of value and className is exclusive."; + messager.printMessage(Kind.ERROR, msg, sourceElement, classSubstition); + messager.printMessage(Kind.ERROR, msg, sourceElement, classSubstition); + } + + return (TypeElement) ((DeclaredType) type).asElement(); + } + + if (classNames.size() != 0) { + TypeElement typeElement = null; + for (String className : classNames) { + typeElement = processor.getTypeElementOrNull(className); + if (typeElement != null) { + break; + } + } + if (typeElement == null && !optional) { + messager.printMessage(Kind.ERROR, String.format("None of the classes %s were found on the classpath.", classNames), sourceElement, classSubstition); + } + + return typeElement; + } + + if (!optional) { + messager.printMessage(Kind.ERROR, String.format("No value for 'value' or 'className' provided."), sourceElement, classSubstition); + } + + return null; + } + +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/FoldHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/FoldHandler.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.processor.AbstractProcessor.getSimpleName; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.TypeKind; +import javax.tools.Diagnostic.Kind; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Handler for the {@value #FOLD_CLASS_NAME} annotation. + */ +public final class FoldHandler extends AnnotationHandler { + + static final String FOLD_CLASS_NAME = "org.graalvm.compiler.api.replacements.Fold"; + static final String INJECTED_PARAMETER_CLASS_NAME = "org.graalvm.compiler.api.replacements.Fold.InjectedParameter"; + + public FoldHandler(AbstractProcessor processor) { + super(processor, FOLD_CLASS_NAME); + } + + @Override + public void process(Element element, AnnotationMirror annotation, PluginGenerator generator) { + if (element.getKind() != ElementKind.METHOD) { + assert false : "Element is guaranteed to be a method."; + return; + } + + ExecutableElement foldMethod = (ExecutableElement) element; + if (foldMethod.getReturnType().getKind() == TypeKind.VOID) { + processor.env().getMessager().printMessage(Kind.ERROR, + String.format("A @%s method must not be void as it won't yield a compile-time constant (the reason for supporting folding!).", getSimpleName(FOLD_CLASS_NAME)), element, + annotation); + } else if (foldMethod.getModifiers().contains(Modifier.PRIVATE)) { + processor.env().getMessager().printMessage(Kind.ERROR, String.format("A @%s method must not be private.", getSimpleName(FOLD_CLASS_NAME)), element, annotation); + } else { + generator.addPlugin(new GeneratedFoldPlugin(foldMethod)); + } + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.replacements.processor.FoldHandler.FOLD_CLASS_NAME; +import static org.graalvm.compiler.replacements.processor.FoldHandler.INJECTED_PARAMETER_CLASS_NAME; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; + +import org.graalvm.compiler.processor.AbstractProcessor; +import org.graalvm.compiler.replacements.processor.InjectedDependencies.WellKnownDependency; + +/** + * Create graph builder plugins for {@code Fold} methods. + */ +public class GeneratedFoldPlugin extends GeneratedPlugin { + + public GeneratedFoldPlugin(ExecutableElement intrinsicMethod) { + super(intrinsicMethod); + } + + @Override + protected TypeElement getAnnotationClass(AbstractProcessor processor) { + return processor.getTypeElement(FOLD_CLASS_NAME); + } + + @Override + public void extraImports(Set imports) { + imports.add("jdk.vm.ci.meta.JavaConstant"); + imports.add("jdk.vm.ci.meta.JavaKind"); + imports.add("org.graalvm.compiler.nodes.ConstantNode"); + } + + @Override + protected InjectedDependencies createExecute(AbstractProcessor processor, PrintWriter out) { + InjectedDependencies deps = new InjectedDependencies(); + List params = intrinsicMethod.getParameters(); + + int argCount = 0; + Object receiver; + if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { + receiver = intrinsicMethod.getEnclosingElement(); + } else { + receiver = "arg0"; + TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); + constantArgument(processor, out, deps, argCount, type.asType(), argCount); + argCount++; + } + + int firstArg = argCount; + for (VariableElement param : params) { + if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) { + constantArgument(processor, out, deps, argCount, param.asType(), argCount); + } else { + out.printf(" assert checkInjectedArgument(b, args[%d], targetMethod);\n", argCount); + out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(processor, (DeclaredType) param.asType())); + } + argCount++; + } + + Set suppressWarnings = new TreeSet<>(); + if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { + suppressWarnings.add("deprecation"); + } + if (hasRawtypeWarning(intrinsicMethod.getReturnType())) { + suppressWarnings.add("rawtypes"); + } + for (VariableElement param : params) { + if (hasUncheckedWarning(param.asType())) { + suppressWarnings.add("unchecked"); + } + } + if (suppressWarnings.size() > 0) { + out.printf(" @SuppressWarnings({"); + String sep = ""; + for (String suppressWarning : suppressWarnings) { + out.printf("%s\"%s\"", sep, suppressWarning); + sep = ", "; + } + out.printf("})\n"); + } + + out.printf(" %s result = %s.%s(", getErasedType(intrinsicMethod.getReturnType()), receiver, intrinsicMethod.getSimpleName()); + if (argCount > firstArg) { + out.printf("arg%d", firstArg); + for (int i = firstArg + 1; i < argCount; i++) { + out.printf(", arg%d", i); + } + } + out.printf(");\n"); + + TypeMirror returnType = intrinsicMethod.getReturnType(); + switch (returnType.getKind()) { + case BOOLEAN: + out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); + break; + case LONG: + out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); + break; + case FLOAT: + out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); + break; + case DOUBLE: + out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); + break; + case ARRAY: + case TYPEVAR: + case DECLARED: + if (returnType.equals(processor.getType("java.lang.String"))) { + out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION)); + } else { + out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION)); + } + break; + default: + throw new IllegalArgumentException(returnType.toString()); + } + + out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH)); + out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); + out.printf(" b.notifyReplacedCall(targetMethod, node);\n"); + out.printf(" return true;\n"); + + return deps; + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.CONSTANT_NODE_PARAMETER_CLASS_NAME; +import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.INJECTED_NODE_PARAMETER_CLASS_NAME; +import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.VALUE_NODE_CLASS_NAME; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Create graph builder plugins for {@code NodeIntrinsic} methods. + */ +public abstract class GeneratedNodeIntrinsicPlugin extends GeneratedPlugin { + + private final TypeMirror[] signature; + + public GeneratedNodeIntrinsicPlugin(ExecutableElement intrinsicMethod, TypeMirror[] signature) { + super(intrinsicMethod); + this.signature = signature; + } + + @Override + protected TypeElement getAnnotationClass(AbstractProcessor processor) { + return processor.getTypeElement(NodeIntrinsicHandler.NODE_INTRINSIC_CLASS_NAME); + } + + protected abstract List getParameters(); + + protected abstract void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount); + + @Override + protected InjectedDependencies createExecute(AbstractProcessor processor, PrintWriter out) { + InjectedDependencies deps = new InjectedDependencies(); + + List params = getParameters(); + + int idx = 0; + for (; idx < params.size(); idx++) { + VariableElement param = params.get(idx); + if (processor.getAnnotation(param, processor.getType(INJECTED_NODE_PARAMETER_CLASS_NAME)) == null) { + break; + } + + out.printf(" %s arg%d = %s;\n", param.asType(), idx, deps.use(processor, (DeclaredType) param.asType())); + } + + for (int i = 0; i < signature.length; i++, idx++) { + if (processor.getAnnotation(intrinsicMethod.getParameters().get(i), processor.getType(CONSTANT_NODE_PARAMETER_CLASS_NAME)) != null) { + constantArgument(processor, out, deps, idx, signature[i], i); + } else { + if (signature[i].equals(processor.getType(VALUE_NODE_CLASS_NAME))) { + out.printf(" ValueNode arg%d = args[%d];\n", idx, i); + } else { + out.printf(" %s arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i); + } + } + } + + factoryCall(processor, out, deps, idx); + + return deps; + } + + public static class ConstructorPlugin extends GeneratedNodeIntrinsicPlugin { + + private final ExecutableElement constructor; + + public ConstructorPlugin(ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) { + super(intrinsicMethod, signature); + this.constructor = constructor; + } + + @Override + public void extraImports(Set imports) { + if (intrinsicMethod.getReturnType().getKind() != TypeKind.VOID) { + imports.add("jdk.vm.ci.meta.JavaKind"); + } + } + + @Override + protected List getParameters() { + return constructor.getParameters(); + } + + @Override + protected void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount) { + out.printf(" %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement()); + if (argCount > 0) { + out.printf("arg0"); + for (int i = 1; i < argCount; i++) { + out.printf(", arg%d", i); + } + } + out.printf(");\n"); + + if (intrinsicMethod.getReturnType().getKind() == TypeKind.VOID) { + out.printf(" b.add(node);\n"); + } else { + out.printf(" b.addPush(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); + } + out.printf(" return true;\n"); + } + } + + public static class CustomFactoryPlugin extends GeneratedNodeIntrinsicPlugin { + + private final ExecutableElement customFactory; + + public CustomFactoryPlugin(ExecutableElement intrinsicMethod, ExecutableElement customFactory, TypeMirror[] signature) { + super(intrinsicMethod, signature); + this.customFactory = customFactory; + } + + @Override + public void extraImports(Set imports) { + } + + @Override + protected List getParameters() { + List ret = customFactory.getParameters(); + // remove initial GraphBuilderContext and ResolvedJavaMethod parameters + return ret.subList(2, ret.size()); + } + + @Override + protected void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount) { + out.printf(" return %s.%s(b, targetMethod", customFactory.getEnclosingElement(), customFactory.getSimpleName()); + for (int i = 0; i < argCount; i++) { + out.printf(", arg%d", i); + } + out.printf(");\n"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import java.io.PrintWriter; +import java.util.Set; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; + +import org.graalvm.compiler.processor.AbstractProcessor; +import org.graalvm.compiler.replacements.processor.InjectedDependencies.Dependency; +import org.graalvm.compiler.replacements.processor.InjectedDependencies.WellKnownDependency; + +public abstract class GeneratedPlugin { + + protected final ExecutableElement intrinsicMethod; + private boolean needInjectionProvider; + + private String pluginName; + + public GeneratedPlugin(ExecutableElement intrinsicMethod) { + this.intrinsicMethod = intrinsicMethod; + this.needInjectionProvider = false; + this.pluginName = intrinsicMethod.getEnclosingElement().getSimpleName() + "_" + intrinsicMethod.getSimpleName(); + } + + protected abstract TypeElement getAnnotationClass(AbstractProcessor processor); + + public String getPluginName() { + return pluginName; + } + + public void setPluginName(String pluginName) { + this.pluginName = pluginName; + } + + public void generate(AbstractProcessor processor, PrintWriter out) { + out.printf(" // class: %s\n", intrinsicMethod.getEnclosingElement()); + out.printf(" // method: %s\n", intrinsicMethod); + out.printf(" // generated-by: %s\n", getClass().getName()); + out.printf(" private static final class %s extends GeneratedInvocationPlugin {\n", pluginName); + out.printf("\n"); + out.printf(" @Override\n"); + out.printf(" public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n"); + InjectedDependencies deps = createExecute(processor, out); + out.printf(" }\n"); + out.printf(" @Override\n"); + out.printf(" public Class getSource() {\n"); + out.printf(" return %s.class;\n", getAnnotationClass(processor).getQualifiedName().toString().replace('$', '.')); + out.printf(" }\n"); + + createPrivateMembers(processor, out, deps); + + out.printf(" }\n"); + } + + public void register(PrintWriter out) { + out.printf(" plugins.register(new %s(", pluginName); + if (needInjectionProvider) { + out.printf("injection"); + } + out.printf("), %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName()); + if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { + out.printf(", InvocationPlugin.Receiver.class"); + } + for (VariableElement arg : intrinsicMethod.getParameters()) { + out.printf(", %s.class", getErasedType(arg.asType())); + } + out.printf(");\n"); + } + + public abstract void extraImports(Set imports); + + protected abstract InjectedDependencies createExecute(AbstractProcessor processor, PrintWriter out); + + static String getErasedType(TypeMirror type) { + switch (type.getKind()) { + case DECLARED: + DeclaredType declared = (DeclaredType) type; + TypeElement element = (TypeElement) declared.asElement(); + return element.getQualifiedName().toString(); + case TYPEVAR: + return getErasedType(((TypeVariable) type).getUpperBound()); + case WILDCARD: + return getErasedType(((WildcardType) type).getExtendsBound()); + case ARRAY: + return getErasedType(((ArrayType) type).getComponentType()) + "[]"; + default: + return type.toString(); + } + } + + static boolean hasRawtypeWarning(TypeMirror type) { + switch (type.getKind()) { + case DECLARED: + DeclaredType declared = (DeclaredType) type; + return declared.getTypeArguments().size() > 0; + case TYPEVAR: + return false; + case WILDCARD: + return false; + case ARRAY: + return hasRawtypeWarning(((ArrayType) type).getComponentType()); + default: + return false; + } + } + + static boolean hasUncheckedWarning(TypeMirror type) { + switch (type.getKind()) { + case DECLARED: + DeclaredType declared = (DeclaredType) type; + for (TypeMirror typeParam : declared.getTypeArguments()) { + if (hasUncheckedWarning(typeParam)) { + return true; + } + } + return false; + case TYPEVAR: + return true; + case WILDCARD: + return ((WildcardType) type).getExtendsBound() != null; + case ARRAY: + return hasUncheckedWarning(((ArrayType) type).getComponentType()); + default: + return false; + } + } + + private void createPrivateMembers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { + if (!deps.isEmpty()) { + out.printf("\n"); + for (Dependency dep : deps) { + out.printf(" private final %s %s;\n", dep.type, dep.name); + } + + out.printf("\n"); + out.printf(" private %s(InjectionProvider injection) {\n", pluginName); + for (Dependency dep : deps) { + out.printf(" this.%s = %s;\n", dep.name, dep.inject(processor, intrinsicMethod)); + } + out.printf(" }\n"); + + needInjectionProvider = true; + } + } + + protected static String getReturnKind(ExecutableElement method) { + switch (method.getReturnType().getKind()) { + case BOOLEAN: + case BYTE: + case SHORT: + case CHAR: + case INT: + return "Int"; + case LONG: + return "Long"; + case FLOAT: + return "Float"; + case DOUBLE: + return "Double"; + case VOID: + return "Void"; + case ARRAY: + case TYPEVAR: + case DECLARED: + return "Object"; + default: + throw new IllegalArgumentException(method.getReturnType().toString()); + } + } + + protected static void constantArgument(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) { + if (hasRawtypeWarning(type)) { + out.printf(" @SuppressWarnings({\"rawtypes\"})\n"); + } + out.printf(" %s arg%d;\n", getErasedType(type), argIdx); + out.printf(" if (args[%d].isConstant()) {\n", nodeIdx); + if (type.equals(processor.getType("jdk.vm.ci.meta.ResolvedJavaType"))) { + out.printf(" arg%d = %s.asJavaType(args[%d].asConstant());\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION), nodeIdx); + } else { + switch (type.getKind()) { + case BOOLEAN: + out.printf(" arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx); + break; + case BYTE: + out.printf(" arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case CHAR: + out.printf(" arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case SHORT: + out.printf(" arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case INT: + out.printf(" arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case LONG: + out.printf(" arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx); + break; + case FLOAT: + out.printf(" arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx); + break; + case DOUBLE: + out.printf(" arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx); + break; + case ARRAY: + case DECLARED: + out.printf(" arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), getErasedType(type), nodeIdx); + break; + default: + throw new IllegalArgumentException(type.toString()); + } + } + out.printf(" } else {\n"); + out.printf(" assert b.canDeferPlugin(this) : b.getClass().toString();\n"); + out.printf(" return false;\n"); + out.printf(" }\n"); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValue; +import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.NODE_INTRINSIC_CLASS_NAME; + +import java.util.HashMap; +import java.util.Iterator; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; + +import org.graalvm.compiler.processor.AbstractProcessor; +import org.graalvm.compiler.replacements.processor.InjectedDependencies.Dependency; + +public class InjectedDependencies implements Iterable { + + public abstract static class Dependency { + + public final String name; + public final String type; + + private Dependency(String name, String type) { + this.name = name; + this.type = type; + } + + public abstract String inject(AbstractProcessor processor, ExecutableElement inject); + } + + private static final class InjectedDependency extends Dependency { + + private InjectedDependency(String name, String type) { + super(name, type); + } + + @Override + public String inject(AbstractProcessor processor, ExecutableElement inject) { + return String.format("injection.getInjectedArgument(%s.class)", type); + } + } + + private static final class InjectedStampDependency extends Dependency { + + private InjectedStampDependency() { + super("stamp", "org.graalvm.compiler.core.common.type.Stamp"); + } + + @Override + public String inject(AbstractProcessor processor, ExecutableElement inject) { + AnnotationMirror nodeIntrinsic = processor.getAnnotation(inject, processor.getType(NODE_INTRINSIC_CLASS_NAME)); + boolean nonNull = nodeIntrinsic != null && getAnnotationValue(nodeIntrinsic, "injectedStampIsNonNull", Boolean.class); + return String.format("injection.getInjectedStamp(%s.class, %s)", GeneratedPlugin.getErasedType(inject.getReturnType()), nonNull); + } + } + + public enum WellKnownDependency { + CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"), + META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"), + INJECTED_STAMP(new InjectedStampDependency()), + SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "org.graalvm.compiler.api.replacements.SnippetReflectionProvider")), + STAMP_PROVIDER("b.getStampProvider()", "org.graalvm.compiler.nodes.spi.StampProvider"), + STRUCTURED_GRAPH("b.getGraph()", "org.graalvm.compiler.nodes.StructuredGraph"); + + private final String expr; + private final String type; + private final Dependency generateMember; + + WellKnownDependency(String expr, String type) { + this.expr = expr; + this.type = type; + this.generateMember = null; + } + + WellKnownDependency(Dependency generateMember) { + this.expr = generateMember.name; + this.type = generateMember.type; + this.generateMember = generateMember; + } + + private TypeMirror getType(AbstractProcessor processor) { + return processor.getType(type); + } + } + + private final HashMap deps; + + public InjectedDependencies() { + deps = new HashMap<>(); + } + + public String use(WellKnownDependency wellKnown) { + if (wellKnown.generateMember != null) { + deps.put(wellKnown.type, wellKnown.generateMember); + } + return wellKnown.expr; + } + + public String use(AbstractProcessor processor, DeclaredType type) { + for (WellKnownDependency wellKnown : WellKnownDependency.values()) { + if (processor.env().getTypeUtils().isAssignable(wellKnown.getType(processor), type)) { + return use(wellKnown); + } + } + + String typeName = type.toString(); + Dependency ret = deps.get(typeName); + if (ret == null) { + ret = new InjectedDependency("injected" + type.asElement().getSimpleName(), typeName); + deps.put(typeName, ret); + } + return ret.name; + } + + @Override + public Iterator iterator() { + return deps.values().iterator(); + } + + public boolean isEmpty() { + return deps.isEmpty(); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/MethodSubstitutionHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/MethodSubstitutionHandler.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValue; +import static org.graalvm.compiler.processor.AbstractProcessor.getSimpleName; +import static org.graalvm.compiler.replacements.processor.ClassSubstitutionHandler.CLASS_SUBSTITUTION_CLASS_NAME; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.annotation.processing.Messager; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.tools.Diagnostic.Kind; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Handler for the {@value #METHOD_SUBSTITUTION_CLASS_NAME} annotation. + */ +public final class MethodSubstitutionHandler extends AnnotationHandler { + + private static final String METHOD_SUBSTITUTION_CLASS_NAME = "org.graalvm.compiler.api.replacements.MethodSubstitution"; + + private static final boolean DEBUG = false; + + private static final String ORIGINAL_METHOD_NAME = "value"; + private static final String ORIGINAL_IS_STATIC = "isStatic"; + private static final String ORIGINAL_SIGNATURE = "signature"; + + private static final String ORIGINAL_METHOD_NAME_DEFAULT = ""; + private static final String ORIGINAL_SIGNATURE_DEFAULT = ""; + + public MethodSubstitutionHandler(AbstractProcessor processor) { + super(processor, METHOD_SUBSTITUTION_CLASS_NAME); + } + + @SuppressWarnings("unused") + @Override + public void process(Element element, AnnotationMirror annotation, PluginGenerator generator) { + if (element.getKind() != ElementKind.METHOD) { + assert false : "Element is guaranteed to be a method."; + return; + } + ExecutableElement substitutionMethod = (ExecutableElement) element; + TypeElement substitutionType = findEnclosingClass(substitutionMethod); + assert substitutionType != null; + + Messager messager = processor.env().getMessager(); + AnnotationMirror substitutionClassAnnotation = processor.getAnnotation(substitutionType, processor.getType(CLASS_SUBSTITUTION_CLASS_NAME)); + if (substitutionClassAnnotation == null) { + messager.printMessage(Kind.ERROR, String.format("A @%s annotation is required on the enclosing class.", getSimpleName(CLASS_SUBSTITUTION_CLASS_NAME)), element, annotation); + return; + } + boolean optional = getAnnotationValue(substitutionClassAnnotation, "optional", Boolean.class); + if (optional) { + return; + } + + TypeElement originalType = ClassSubstitutionHandler.resolveOriginalType(processor, substitutionType, substitutionClassAnnotation); + if (originalType == null) { + messager.printMessage(Kind.ERROR, String.format("The @%s annotation is invalid on the enclosing class.", getSimpleName(CLASS_SUBSTITUTION_CLASS_NAME)), element, annotation); + return; + } + + if (!substitutionMethod.getModifiers().contains(Modifier.STATIC)) { + messager.printMessage(Kind.ERROR, String.format("A @%s method must be static.", getSimpleName(METHOD_SUBSTITUTION_CLASS_NAME)), element, annotation); + } + + if (substitutionMethod.getModifiers().contains(Modifier.ABSTRACT) || substitutionMethod.getModifiers().contains(Modifier.NATIVE)) { + messager.printMessage(Kind.ERROR, String.format("A @%s method must not be native or abstract.", getSimpleName(METHOD_SUBSTITUTION_CLASS_NAME)), element, annotation); + } + + String originalName = originalName(substitutionMethod, annotation); + boolean isStatic = getAnnotationValue(annotation, ORIGINAL_IS_STATIC, Boolean.class); + TypeMirror[] originalSignature = originalSignature(originalType, substitutionMethod, annotation, isStatic); + if (originalSignature == null) { + return; + } + ExecutableElement originalMethod = originalMethod(substitutionMethod, annotation, originalType, originalName, originalSignature, isStatic); + if (DEBUG && originalMethod != null) { + messager.printMessage(Kind.NOTE, String.format("Found original method %s in type %s.", originalMethod, findEnclosingClass(originalMethod))); + } + } + + private TypeMirror[] originalSignature(TypeElement originalType, ExecutableElement method, AnnotationMirror annotation, boolean isStatic) { + String signatureString = getAnnotationValue(annotation, ORIGINAL_SIGNATURE, String.class); + List parameters = new ArrayList<>(); + Messager messager = processor.env().getMessager(); + if (signatureString.equals(ORIGINAL_SIGNATURE_DEFAULT)) { + for (int i = 0; i < method.getParameters().size(); i++) { + parameters.add(method.getParameters().get(i).asType()); + } + if (!isStatic) { + if (parameters.isEmpty()) { + messager.printMessage(Kind.ERROR, "Method signature must be a static method with the 'this' object as its first parameter", method, annotation); + return null; + } else { + TypeMirror thisParam = parameters.remove(0); + if (!isSubtype(originalType.asType(), thisParam)) { + Name thisName = method.getParameters().get(0).getSimpleName(); + messager.printMessage(Kind.ERROR, String.format("The type of %s must assignable from %s", thisName, originalType), method, annotation); + } + } + } + parameters.add(0, method.getReturnType()); + } else { + try { + APHotSpotSignature signature = new APHotSpotSignature(signatureString); + parameters.add(signature.getReturnType(processor.env())); + for (int i = 0; i < signature.getParameterCount(false); i++) { + parameters.add(signature.getParameterType(processor.env(), i)); + } + } catch (Exception e) { + /* + * That's not good practice and should be changed after APHotSpotSignature has + * received a cleanup. + */ + messager.printMessage(Kind.ERROR, String.format("Parsing the signature failed: %s", e.getMessage() != null ? e.getMessage() : e.toString()), method, annotation); + return null; + } + } + return parameters.toArray(new TypeMirror[parameters.size()]); + } + + private static String originalName(ExecutableElement substituteMethod, AnnotationMirror substitution) { + String originalMethodName = getAnnotationValue(substitution, ORIGINAL_METHOD_NAME, String.class); + if (originalMethodName.equals(ORIGINAL_METHOD_NAME_DEFAULT)) { + originalMethodName = substituteMethod.getSimpleName().toString(); + } + return originalMethodName; + } + + private ExecutableElement originalMethod(ExecutableElement substitutionMethod, AnnotationMirror substitutionAnnotation, TypeElement originalType, String originalName, + TypeMirror[] originalSignature, boolean isStatic) { + TypeMirror signatureReturnType = originalSignature[0]; + TypeMirror[] signatureParameters = Arrays.copyOfRange(originalSignature, 1, originalSignature.length); + List searchElements; + if (originalName.equals("")) { + searchElements = ElementFilter.constructorsIn(originalType.getEnclosedElements()); + } else { + searchElements = ElementFilter.methodsIn(originalType.getEnclosedElements()); + } + + Messager messager = processor.env().getMessager(); + ExecutableElement originalMethod = null; + outer: for (ExecutableElement searchElement : searchElements) { + if (searchElement.getSimpleName().toString().equals(originalName) && searchElement.getParameters().size() == signatureParameters.length) { + for (int i = 0; i < signatureParameters.length; i++) { + VariableElement parameter = searchElement.getParameters().get(i); + if (!isTypeCompatible(parameter.asType(), signatureParameters[i])) { + continue outer; + } + } + originalMethod = searchElement; + break; + } + } + if (originalMethod == null) { + boolean optional = getAnnotationValue(substitutionAnnotation, "optional", Boolean.class); + if (!optional) { + messager.printMessage(Kind.ERROR, + String.format("Could not find the original method with name '%s' and parameters '%s'.", originalName, Arrays.toString(signatureParameters)), + substitutionMethod, substitutionAnnotation); + } + return null; + } + + if (originalMethod.getModifiers().contains(Modifier.STATIC) != isStatic) { + boolean optional = getAnnotationValue(substitutionAnnotation, "optional", Boolean.class); + if (!optional) { + messager.printMessage(Kind.ERROR, String.format("The %s element must be set to %s.", ORIGINAL_IS_STATIC, !isStatic), substitutionMethod, substitutionAnnotation); + } + return null; + } + + if (!isTypeCompatible(originalMethod.getReturnType(), signatureReturnType)) { + messager.printMessage( + Kind.ERROR, + String.format("The return type of the substitution method '%s' must match with the return type of the original method '%s'.", signatureReturnType, + originalMethod.getReturnType()), + substitutionMethod, substitutionAnnotation); + return null; + } + + return originalMethod; + } + + private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { + TypeMirror original = originalType; + TypeMirror substitution = substitutionType; + if (needsErasure(original)) { + original = processor.env().getTypeUtils().erasure(original); + } + if (needsErasure(substitution)) { + substitution = processor.env().getTypeUtils().erasure(substitution); + } + return processor.env().getTypeUtils().isSameType(original, substitution); + } + + /** + * Tests whether one type is a subtype of another. Any type is considered to be a subtype of + * itself. + * + * @param t1 the first type + * @param t2 the second type + * @return {@code true} if and only if the first type is a subtype of the second + */ + private boolean isSubtype(TypeMirror t1, TypeMirror t2) { + TypeMirror t1Erased = t1; + TypeMirror t2Erased = t2; + if (needsErasure(t1Erased)) { + t1Erased = processor.env().getTypeUtils().erasure(t1Erased); + } + if (needsErasure(t2Erased)) { + t2Erased = processor.env().getTypeUtils().erasure(t2Erased); + } + return processor.env().getTypeUtils().isSubtype(t1Erased, t2Erased); + } + + private static boolean needsErasure(TypeMirror typeMirror) { + return typeMirror.getKind() != TypeKind.NONE && typeMirror.getKind() != TypeKind.VOID && !typeMirror.getKind().isPrimitive() && typeMirror.getKind() != TypeKind.OTHER && + typeMirror.getKind() != TypeKind.NULL; + } + + private static TypeElement findEnclosingClass(Element element) { + if (element.getKind().isClass()) { + return (TypeElement) element; + } + + Element enclosing = element.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + if (enclosing.getKind().isClass()) { + return (TypeElement) enclosing; + } + enclosing = enclosing.getEnclosingElement(); + } + return null; + } + +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValue; +import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValueList; +import static org.graalvm.compiler.processor.AbstractProcessor.getSimpleName; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Formatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.processing.Messager; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.util.ElementFilter; +import javax.tools.Diagnostic.Kind; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Handler for the {@value #NODE_INFO_CLASS_NAME} annotation. + */ +public final class NodeIntrinsicHandler extends AnnotationHandler { + + static final String CONSTANT_NODE_PARAMETER_CLASS_NAME = "org.graalvm.compiler.graph.Node.ConstantNodeParameter"; + static final String MARKER_TYPE_CLASS_NAME = "org.graalvm.compiler.nodeinfo.StructuralInput.MarkerType"; + static final String GRAPH_BUILDER_CONTEXT_CLASS_NAME = "org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext"; + static final String STRUCTURAL_INPUT_CLASS_NAME = "org.graalvm.compiler.nodeinfo.StructuralInput"; + static final String RESOLVED_JAVA_METHOD_CLASS_NAME = "jdk.vm.ci.meta.ResolvedJavaMethod"; + static final String RESOLVED_JAVA_TYPE_CLASS_NAME = "jdk.vm.ci.meta.ResolvedJavaType"; + static final String VALUE_NODE_CLASS_NAME = "org.graalvm.compiler.nodes.ValueNode"; + static final String STAMP_CLASS_NAME = "org.graalvm.compiler.core.common.type.Stamp"; + static final String NODE_CLASS_NAME = "org.graalvm.compiler.graph.Node"; + static final String NODE_INFO_CLASS_NAME = "org.graalvm.compiler.nodeinfo.NodeInfo"; + static final String NODE_INTRINSIC_CLASS_NAME = "org.graalvm.compiler.graph.Node.NodeIntrinsic"; + static final String INJECTED_NODE_PARAMETER_CLASS_NAME = "org.graalvm.compiler.graph.Node.InjectedNodeParameter"; + + public NodeIntrinsicHandler(AbstractProcessor processor) { + super(processor, NODE_INTRINSIC_CLASS_NAME); + } + + @Override + public void process(Element element, AnnotationMirror annotation, PluginGenerator generator) { + if (element.getKind() != ElementKind.METHOD) { + assert false : "Element is guaranteed to be a method."; + return; + } + + ExecutableElement intrinsicMethod = (ExecutableElement) element; + Messager messager = processor.env().getMessager(); + if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { + messager.printMessage(Kind.ERROR, String.format("A @%s method must be static.", getSimpleName(NODE_INTRINSIC_CLASS_NAME)), element, annotation); + } + if (!intrinsicMethod.getModifiers().contains(Modifier.NATIVE)) { + messager.printMessage(Kind.ERROR, String.format("A @%s method must be native.", getSimpleName(NODE_INTRINSIC_CLASS_NAME)), element, annotation); + } + + TypeMirror nodeClassMirror = getAnnotationValue(annotation, "value", TypeMirror.class); + TypeElement nodeClass = processor.asTypeElement(nodeClassMirror); + if (processor.env().getTypeUtils().isSameType(nodeClassMirror, annotation.getAnnotationType())) { + // default value + Element enclosingElement = intrinsicMethod.getEnclosingElement(); + while (enclosingElement != null && enclosingElement.getKind() != ElementKind.CLASS) { + enclosingElement = enclosingElement.getEnclosingElement(); + } + if (enclosingElement != null) { + nodeClass = (TypeElement) enclosingElement; + } + } + + TypeMirror returnType = intrinsicMethod.getReturnType(); + if (returnType instanceof TypeVariable) { + messager.printMessage(Kind.ERROR, "@NodeIntrinsic cannot have a generic return type.", element, annotation); + } + + boolean injectedStampIsNonNull = getAnnotationValue(annotation, "injectedStampIsNonNull", Boolean.class); + + if (returnType.getKind() == TypeKind.VOID) { + for (VariableElement parameter : intrinsicMethod.getParameters()) { + if (processor.getAnnotation(parameter, processor.getType(INJECTED_NODE_PARAMETER_CLASS_NAME)) != null) { + messager.printMessage(Kind.ERROR, "@NodeIntrinsic with an injected Stamp parameter cannot have a void return type.", element, annotation); + break; + } + } + } + + TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); + Map nonMatches = new HashMap<>(); + List factories = findIntrinsifyFactoryMethod(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); + List constructors = Collections.emptyList(); + if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { + if (factories.isEmpty()) { + messager.printMessage(Kind.ERROR, String.format("Cannot make a node intrinsic for abstract class %s.", nodeClass.getSimpleName()), element, annotation); + } + } else if (!isNodeType(nodeClass)) { + if (factories.isEmpty()) { + messager.printMessage(Kind.ERROR, String.format("%s is not a subclass of %s.", nodeClass.getSimpleName(), processor.getType(NODE_CLASS_NAME)), element, annotation); + } + } else { + TypeMirror ret = returnType; + if (processor.env().getTypeUtils().isAssignable(ret, processor.getType(STRUCTURAL_INPUT_CLASS_NAME))) { + checkInputType(nodeClass, ret, element, annotation); + } + + constructors = findConstructors(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); + } + Formatter msg = new Formatter(); + if (factories.size() > 1) { + msg.format("Found more than one factory in %s matching node intrinsic:", nodeClass); + for (ExecutableElement candidate : factories) { + msg.format("%n %s", candidate); + } + messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); + } else if (constructors.size() > 1) { + msg.format("Found more than one constructor in %s matching node intrinsic:", nodeClass); + for (ExecutableElement candidate : constructors) { + msg.format("%n %s", candidate); + } + messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); + } else if (factories.size() == 1) { + generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, factories.get(0), constructorSignature)); + } else if (constructors.size() == 1) { + generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructors.get(0), constructorSignature)); + } else { + msg.format("Could not find any factories or constructors in %s matching node intrinsic", nodeClass); + if (!nonMatches.isEmpty()) { + msg.format("%nFactories and constructors that failed to match:"); + for (Map.Entry e : nonMatches.entrySet()) { + msg.format("%n %s: %s", e.getKey(), e.getValue()); + } + } + messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); + } + } + + private void checkInputType(TypeElement nodeClass, TypeMirror returnType, Element element, AnnotationMirror annotation) { + String inputType = getInputType(returnType, element, annotation); + if (!inputType.equals("Value")) { + boolean allowed = false; + List allowedTypes = getAnnotationValueList(processor.getAnnotation(nodeClass, processor.getType(NODE_INFO_CLASS_NAME)), "allowedUsageTypes", VariableElement.class); + for (VariableElement allowedType : allowedTypes) { + if (allowedType.getSimpleName().contentEquals(inputType)) { + allowed = true; + break; + } + } + if (!allowed) { + processor.env().getMessager().printMessage(Kind.ERROR, String.format("@NodeIntrinsic returns input type %s, but only %s is allowed.", inputType, allowedTypes), element, annotation); + } + } + } + + private String getInputType(TypeMirror type, Element element, AnnotationMirror annotation) { + TypeElement current = processor.asTypeElement(type); + while (current != null) { + AnnotationMirror markerType = processor.getAnnotation(current, processor.getType(MARKER_TYPE_CLASS_NAME)); + if (markerType != null) { + return getAnnotationValue(markerType, "value", VariableElement.class).getSimpleName().toString(); + } + + current = processor.asTypeElement(current.getSuperclass()); + } + + processor.env().getMessager().printMessage(Kind.ERROR, + String.format("The class %s is a subclass of StructuralInput, but isn't annotated with @MarkerType. %s", type, element.getAnnotationMirrors()), + element, annotation); + return "Value"; + } + + private boolean isNodeType(TypeElement nodeClass) { + return processor.env().getTypeUtils().isSubtype(nodeClass.asType(), processor.getType(NODE_CLASS_NAME)); + } + + private TypeMirror[] constructorSignature(ExecutableElement method) { + TypeMirror[] parameters = new TypeMirror[method.getParameters().size()]; + for (int i = 0; i < method.getParameters().size(); i++) { + VariableElement parameter = method.getParameters().get(i); + if (processor.getAnnotation(parameter, processor.getType(CONSTANT_NODE_PARAMETER_CLASS_NAME)) == null) { + parameters[i] = processor.getType(VALUE_NODE_CLASS_NAME); + } else { + TypeMirror type = parameter.asType(); + if (isTypeCompatible(type, processor.getType("java.lang.Class"))) { + type = processor.getType(RESOLVED_JAVA_TYPE_CLASS_NAME); + } + parameters[i] = type; + } + } + return parameters; + } + + private List findConstructors(TypeElement nodeClass, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { + List constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements()); + List found = new ArrayList<>(constructors.size()); + for (ExecutableElement constructor : constructors) { + if (matchSignature(0, constructor, signature, nonMatches, requiresInjectedStamp)) { + found.add(constructor); + } + } + return found; + } + + private List findIntrinsifyFactoryMethod(TypeElement nodeClass, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { + List methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); + List found = new ArrayList<>(methods.size()); + for (ExecutableElement method : methods) { + if (!method.getSimpleName().toString().equals("intrinsify")) { + continue; + } + + if (method.getParameters().size() < 2) { + continue; + } + + VariableElement firstArg = method.getParameters().get(0); + if (!isTypeCompatible(firstArg.asType(), processor.getType(GRAPH_BUILDER_CONTEXT_CLASS_NAME))) { + continue; + } + + VariableElement secondArg = method.getParameters().get(1); + if (!isTypeCompatible(secondArg.asType(), processor.getType(RESOLVED_JAVA_METHOD_CLASS_NAME))) { + continue; + } + + if (method.getReturnType().getKind() != TypeKind.BOOLEAN) { + continue; + } + + if (matchSignature(2, method, signature, nonMatches, requiresInjectedStamp)) { + found.add(method); + } + } + return found; + } + + private boolean matchSignature(int numSkippedParameters, ExecutableElement method, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { + int sIdx = 0; + int cIdx = numSkippedParameters; + boolean missingStampArgument = requiresInjectedStamp; + while (cIdx < method.getParameters().size()) { + VariableElement parameter = method.getParameters().get(cIdx++); + TypeMirror paramType = parameter.asType(); + if (processor.getAnnotation(parameter, processor.getType(INJECTED_NODE_PARAMETER_CLASS_NAME)) != null) { + if (missingStampArgument && processor.env().getTypeUtils().isSameType(paramType, processor.getType(STAMP_CLASS_NAME))) { + missingStampArgument = false; + } + // skip injected parameters + continue; + } + if (missingStampArgument) { + nonMatches.put(method, String.format("missing injected %s argument", processor.getType(STAMP_CLASS_NAME))); + return false; + } + + if (cIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { + // last argument of constructor is varargs, match remaining intrinsic arguments + TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); + while (sIdx < signature.length) { + if (!isTypeCompatible(varargsType, signature[sIdx++])) { + nonMatches.put(method, String.format("the types of argument %d are incompatible: %s != %s", sIdx, varargsType, signature[sIdx - 1])); + return false; + } + } + } else if (sIdx >= signature.length) { + // too many arguments in intrinsic method + nonMatches.put(method, "too many arguments"); + return false; + } else if (!isTypeCompatible(paramType, signature[sIdx++])) { + nonMatches.put(method, String.format("the type of argument %d is incompatible: %s != %s", sIdx, paramType, signature[sIdx - 1])); + return false; + } + } + if (missingStampArgument) { + nonMatches.put(method, String.format("missing injected %s argument", processor.getType(STAMP_CLASS_NAME))); + return false; + } + + if (sIdx != signature.length) { + nonMatches.put(method, "not enough arguments"); + return false; + } + return true; + } + + private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { + TypeMirror original = originalType; + TypeMirror substitution = substitutionType; + if (needsErasure(original)) { + original = processor.env().getTypeUtils().erasure(original); + } + if (needsErasure(substitution)) { + substitution = processor.env().getTypeUtils().erasure(substitution); + } + return processor.env().getTypeUtils().isSameType(original, substitution); + } + + private static boolean needsErasure(TypeMirror typeMirror) { + return typeMirror.getKind() != TypeKind.NONE && typeMirror.getKind() != TypeKind.VOID && !typeMirror.getKind().isPrimitive() && typeMirror.getKind() != TypeKind.OTHER && + typeMirror.getKind() != TypeKind.NULL; + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Function; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +import org.graalvm.compiler.processor.AbstractProcessor; + +public class PluginGenerator { + + private final Map> plugins; + + public PluginGenerator() { + this.plugins = new HashMap<>(); + } + + public void addPlugin(GeneratedPlugin plugin) { + Element topLevel = getTopLevelClass(plugin.intrinsicMethod); + List list = plugins.get(topLevel); + if (list == null) { + list = new ArrayList<>(); + plugins.put(topLevel, list); + } + list.add(plugin); + } + + public void generateAll(AbstractProcessor processor) { + for (Entry> entry : plugins.entrySet()) { + disambiguateNames(entry.getValue()); + createPluginFactory(processor, entry.getKey(), entry.getValue()); + } + } + + private static Element getTopLevelClass(Element element) { + Element prev = element; + Element enclosing = element.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + prev = enclosing; + enclosing = enclosing.getEnclosingElement(); + } + return prev; + } + + private static void disambiguateWith(List plugins, Function genName) { + plugins.sort(Comparator.comparing(GeneratedPlugin::getPluginName)); + + GeneratedPlugin current = plugins.get(0); + String currentName = current.getPluginName(); + + for (int i = 1; i < plugins.size(); i++) { + GeneratedPlugin next = plugins.get(i); + if (currentName.equals(next.getPluginName())) { + if (current != null) { + current.setPluginName(genName.apply(current)); + current = null; + } + next.setPluginName(genName.apply(next)); + } else { + current = next; + currentName = current.getPluginName(); + } + } + } + + private static void appendSimpleTypeName(StringBuilder ret, TypeMirror type) { + switch (type.getKind()) { + case DECLARED: + DeclaredType declared = (DeclaredType) type; + TypeElement element = (TypeElement) declared.asElement(); + ret.append(element.getSimpleName()); + break; + case TYPEVAR: + appendSimpleTypeName(ret, ((TypeVariable) type).getUpperBound()); + break; + case WILDCARD: + appendSimpleTypeName(ret, ((WildcardType) type).getExtendsBound()); + break; + case ARRAY: + appendSimpleTypeName(ret, ((ArrayType) type).getComponentType()); + ret.append("Array"); + break; + default: + ret.append(type); + } + } + + private static void disambiguateNames(List plugins) { + // if we have more than one method with the same name, disambiguate with the argument types + disambiguateWith(plugins, plugin -> { + StringBuilder ret = new StringBuilder(plugin.getPluginName()); + for (VariableElement param : plugin.intrinsicMethod.getParameters()) { + ret.append('_'); + appendSimpleTypeName(ret, param.asType()); + } + return ret.toString(); + }); + + // since we're using simple names for argument types, we could still have a collision + disambiguateWith(plugins, new Function() { + + private int idx = 0; + + @Override + public String apply(GeneratedPlugin plugin) { + return plugin.getPluginName() + "_" + (idx++); + } + }); + } + + private static void createPluginFactory(AbstractProcessor processor, Element topLevelClass, List plugins) { + PackageElement pkg = (PackageElement) topLevelClass.getEnclosingElement(); + + String genClassName = "PluginFactory_" + topLevelClass.getSimpleName(); + + String qualifiedGenClassName = pkg.getQualifiedName() + "." + genClassName; + try { + JavaFileObject factory = processor.env().getFiler().createSourceFile(qualifiedGenClassName, topLevelClass); + try (PrintWriter out = new PrintWriter(factory.openWriter())) { + out.printf("// CheckStyle: stop header check\n"); + out.printf("// CheckStyle: stop line length check\n"); + out.printf("// GENERATED CONTENT - DO NOT EDIT\n"); + out.printf("// GENERATORS: %s, %s\n", ReplacementsAnnotationProcessor.class.getName(), PluginGenerator.class.getName()); + out.printf("package %s;\n", pkg.getQualifiedName()); + out.printf("\n"); + createImports(out, plugins); + out.printf("\n"); + out.printf("public class %s implements NodeIntrinsicPluginFactory {\n", genClassName); + for (GeneratedPlugin plugin : plugins) { + out.printf("\n"); + plugin.generate(processor, out); + } + out.printf("\n"); + createPluginFactoryMethod(out, plugins); + out.printf("}\n"); + } + } catch (IOException e) { + processor.env().getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + } + processor.createProviderFile(qualifiedGenClassName, "org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory", topLevelClass); + } + + protected static void createImports(PrintWriter out, List plugins) { + out.printf("import jdk.vm.ci.meta.ResolvedJavaMethod;\n"); + out.printf("\n"); + out.printf("import java.lang.annotation.Annotation;\n"); + out.printf("import org.graalvm.compiler.nodes.ValueNode;\n"); + out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;\n"); + out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;\n"); + out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;\n"); + out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;\n"); + out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;\n"); + + HashSet extra = new HashSet<>(); + for (GeneratedPlugin plugin : plugins) { + plugin.extraImports(extra); + } + if (!extra.isEmpty()) { + out.printf("\n"); + for (String i : extra) { + out.printf("import %s;\n", i); + } + } + } + + private static void createPluginFactoryMethod(PrintWriter out, List plugins) { + out.printf(" @Override\n"); + out.printf(" public void registerPlugins(InvocationPlugins plugins, InjectionProvider injection) {\n"); + for (GeneratedPlugin plugin : plugins) { + plugin.register(out); + } + out.printf(" }\n"); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ReplacementsAnnotationProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ReplacementsAnnotationProcessor.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.processor; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; + +import org.graalvm.compiler.processor.AbstractProcessor; + +/** + * Processor for annotation types in the {@code org.graalvm.compiler.replacements} name space. + */ +public class ReplacementsAnnotationProcessor extends AbstractProcessor { + + private List handlers; + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + PluginGenerator generator = new PluginGenerator(); + for (AnnotationHandler handler : getHandlers()) { + TypeElement annotationClass = getTypeElementOrNull(handler.annotationTypeName); + if (annotationClass != null) { + for (Element e : roundEnv.getElementsAnnotatedWith(annotationClass)) { + AnnotationMirror annotationMirror = getAnnotation(e, annotationClass.asType()); + handler.process(e, annotationMirror, generator); + } + } else { + Set roots = roundEnv.getRootElements(); + String message = String.format("Processor %s disabled as %s is not resolvable on the compilation class path", handler.getClass().getName(), handler.annotationTypeName); + if (roots.isEmpty()) { + env().getMessager().printMessage(Kind.WARNING, message); + } else { + env().getMessager().printMessage(Kind.WARNING, message, roots.iterator().next()); + } + } + } + generator.generateAll(this); + } + return false; + } + + public List getHandlers() { + if (handlers == null) { + handlers = new ArrayList<>(); + handlers.add(new ClassSubstitutionHandler(this)); + handlers.add(new MethodSubstitutionHandler(this)); + handlers.add(new NodeIntrinsicHandler(this)); + handlers.add(new FoldHandler(this)); + } + return handlers; + } + + @Override + public Set getSupportedAnnotationTypes() { + Set annotationTypes = new HashSet<>(); + for (AnnotationHandler handler : getHandlers()) { + annotationTypes.add(handler.annotationTypeName); + } + return annotationTypes; + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.sparc/src/org/graalvm/compiler/replacements/sparc/SPARCGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.sparc/src/org/graalvm/compiler/replacements/sparc/SPARCGraphBuilderPlugins.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.sparc/src/org/graalvm/compiler/replacements/sparc/SPARCGraphBuilderPlugins.java Thu May 31 13:39:26 2018 -0700 @@ -38,6 +38,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.replacements.IntegerSubstitutions; import org.graalvm.compiler.replacements.LongSubstitutions; +import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.BitCountNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; @@ -56,6 +57,10 @@ registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider); registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, bytecodeProvider); registerMathPlugins(invocationPlugins); + // This is temporarily disabled until we implement correct emitting of the CAS + // instructions of the proper width. + StandardGraphBuilderPlugins.registerPlatformSpecificUnsafePlugins(invocationPlugins, bytecodeProvider, + new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}); } }); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArrayStoreBytecodeExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArrayStoreBytecodeExceptionTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArrayStoreBytecodeExceptionTest.java Thu May 31 13:39:26 2018 -0700 @@ -32,6 +32,7 @@ import org.junit.runners.Parameterized.Parameters; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -55,7 +56,7 @@ invocationPlugins.register(new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode obj) { - return throwBytecodeException(b, ArrayStoreException.class, obj); + return throwBytecodeException(b, BytecodeExceptionKind.ARRAY_STORE, obj); } }, Exceptions.class, "throwArrayStore", Object.class); super.registerInvocationPlugins(invocationPlugins); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BytecodeExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BytecodeExceptionTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BytecodeExceptionTest.java Thu May 31 13:39:26 2018 -0700 @@ -26,11 +26,12 @@ import org.graalvm.compiler.nodes.UnwindNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; public abstract class BytecodeExceptionTest extends GraalCompilerTest { - protected boolean throwBytecodeException(GraphBuilderContext b, Class exception, ValueNode... arguments) { + protected boolean throwBytecodeException(GraphBuilderContext b, BytecodeExceptionKind exception, ValueNode... arguments) { BytecodeExceptionNode exceptionNode = b.add(new BytecodeExceptionNode(b.getMetaAccess(), exception, arguments)); b.add(new UnwindNode(exceptionNode)); return true; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ClassCastBytecodeExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ClassCastBytecodeExceptionTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ClassCastBytecodeExceptionTest.java Thu May 31 13:39:26 2018 -0700 @@ -38,6 +38,7 @@ import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -83,7 +84,7 @@ Constant hub = b.getConstantReflection().asObjectHub(type); Stamp hubStamp = b.getStampProvider().createHubStamp(StampFactory.object(TypeReference.createExactTrusted(type))); ConstantNode hubConst = b.add(ConstantNode.forConstant(hubStamp, hub, b.getMetaAccess())); - return throwBytecodeException(b, ClassCastException.class, obj, hubConst); + return throwBytecodeException(b, BytecodeExceptionKind.CLASS_CAST, obj, hubConst); } }, Exceptions.class, "throwClassCast", Object.class, Class.class); super.registerInvocationPlugins(invocationPlugins); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IndexOobBytecodeExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IndexOobBytecodeExceptionTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IndexOobBytecodeExceptionTest.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -46,8 +47,9 @@ private static Object[] empty = new Object[0]; - public static void throwOutOfBounds(int idx) { + public static void throwOutOfBounds(int idx, int length) { GraalDirectives.blackhole(empty[idx]); + GraalDirectives.blackhole(length); } } @@ -55,15 +57,15 @@ protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { invocationPlugins.register(new InvocationPlugin() { @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode idx) { - return throwBytecodeException(b, ArrayIndexOutOfBoundsException.class, idx); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode idx, ValueNode length) { + return throwBytecodeException(b, BytecodeExceptionKind.OUT_OF_BOUNDS, idx, length); } - }, Exceptions.class, "throwOutOfBounds", int.class); + }, Exceptions.class, "throwOutOfBounds", int.class, int.class); super.registerInvocationPlugins(invocationPlugins); } - public static void oobSnippet(int idx) { - Exceptions.throwOutOfBounds(idx); + public static void oobSnippet(int idx, int length) { + Exceptions.throwOutOfBounds(idx, length); } @Parameter public int index; @@ -81,6 +83,6 @@ @Test public void testOutOfBoundsException() { - test("oobSnippet", index); + test("oobSnippet", index, Exceptions.empty.length); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NullBytecodeExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NullBytecodeExceptionTest.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NullBytecodeExceptionTest.java Thu May 31 13:39:26 2018 -0700 @@ -23,7 +23,7 @@ package org.graalvm.compiler.replacements.test; import org.junit.Test; - +import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -46,7 +46,7 @@ invocationPlugins.register(new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - return throwBytecodeException(b, NullPointerException.class); + return throwBytecodeException(b, BytecodeExceptionKind.NULL_POINTER); } }, Exceptions.class, "throwNull"); super.registerInvocationPlugins(invocationPlugins); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/META-INF/services/javax.annotation.processing.Processor --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/META-INF/services/javax.annotation.processing.Processor Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -org.graalvm.compiler.replacements.verifier.VerifierAnnotationProcessor diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/APHotSpotSignature.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/APHotSpotSignature.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.tools.Diagnostic.Kind; - -/** - * Pretty much copied from HotSpotSignature but using a different method for resolving types. This - * class should be rewritten, its just a quick hack to get signatures working. - */ -final class APHotSpotSignature { - - private final List arguments = new ArrayList<>(); - private final String returnType; - private final String originalString; - private TypeMirror[] argumentTypes; - private TypeMirror returnTypeCache; - - APHotSpotSignature(String signature) { - assert signature.length() > 0; - this.originalString = signature; - - if (signature.charAt(0) == '(') { - int cur = 1; - while (cur < signature.length() && signature.charAt(cur) != ')') { - int nextCur = parseSignature(signature, cur); - arguments.add(signature.substring(cur, nextCur)); - cur = nextCur; - } - - cur++; - int nextCur = parseSignature(signature, cur); - returnType = signature.substring(cur, nextCur); - if (nextCur != signature.length()) { - throw new RuntimeException("Invalid trailing characters."); - } - } else { - returnType = null; - } - } - - private static int parseSignature(String signature, int start) { - int cur = start; - char first; - do { - first = signature.charAt(cur++); - } while (first == '['); - - switch (first) { - case 'L': - while (signature.charAt(cur) != ';') { - cur++; - } - cur++; - break; - case 'V': - case 'I': - case 'B': - case 'C': - case 'D': - case 'F': - case 'J': - case 'S': - case 'Z': - break; - default: - throw new RuntimeException("Invalid character at index " + cur + " in signature: " + signature); - } - return cur; - } - - public int getParameterCount(boolean withReceiver) { - return arguments.size() + (withReceiver ? 1 : 0); - } - - public TypeMirror getParameterType(ProcessingEnvironment env, int index) { - if (argumentTypes == null) { - argumentTypes = new TypeMirror[arguments.size()]; - } - TypeMirror type = argumentTypes[index]; - if (arguments.get(index) == null) { - throw new RuntimeException(String.format("Invalid argument at index %s.", index)); - } - - if (type == null) { - argumentTypes[index] = lookupType(env, arguments.get(index)); - } - return argumentTypes[index]; - } - - private static TypeMirror lookupType(ProcessingEnvironment env, String binaryName) { - if (binaryName.length() == 1) { - TypeKind kind = fromPrimitiveOrVoidTypeChar(binaryName.charAt(0)); - if (kind.isPrimitive()) { - return env.getTypeUtils().getPrimitiveType(kind); - } else if (kind == TypeKind.VOID) { - return env.getTypeUtils().getNoType(kind); - } - } - - String canonicalName = binaryName; - if (canonicalName.startsWith("L") && canonicalName.endsWith(";")) { - canonicalName = canonicalName.substring(1, canonicalName.length() - 1); - } - env.getMessager().printMessage(Kind.ERROR, canonicalName); - - int arrayDims = 0; - while (canonicalName.startsWith("[")) { - canonicalName = canonicalName.substring(1, canonicalName.length()); - arrayDims++; - } - - canonicalName = canonicalName.replaceAll("/", "."); - TypeElement typeElement = env.getElementUtils().getTypeElement(canonicalName); - if (typeElement == null) { - throw new RuntimeException(String.format("Type with name %s not found.", canonicalName)); - } - TypeMirror mirror = typeElement.asType(); - for (int i = 0; i < arrayDims; i++) { - mirror = env.getTypeUtils().getArrayType(mirror); - } - return mirror; - } - - /** - * Returns the kind from the character describing a primitive or void. - * - * @param ch the character - * @return the kind - */ - public static TypeKind fromPrimitiveOrVoidTypeChar(char ch) { - switch (ch) { - case 'Z': - return TypeKind.BOOLEAN; - case 'C': - return TypeKind.CHAR; - case 'F': - return TypeKind.FLOAT; - case 'D': - return TypeKind.DOUBLE; - case 'B': - return TypeKind.BYTE; - case 'S': - return TypeKind.SHORT; - case 'I': - return TypeKind.INT; - case 'J': - return TypeKind.LONG; - case 'V': - return TypeKind.VOID; - } - throw new IllegalArgumentException("unknown primitive or void type character: " + ch); - } - - public TypeMirror getReturnType(ProcessingEnvironment env) { - if (returnTypeCache == null) { - if (returnType == null) { - throw new RuntimeException("Invalid return type."); - } - returnTypeCache = lookupType(env, returnType); - } - return returnTypeCache; - } - - @Override - public String toString() { - return "Signature<" + originalString + ">"; - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/AbstractVerifier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/AbstractVerifier.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; - -public abstract class AbstractVerifier { - - protected final ProcessingEnvironment env; - - public AbstractVerifier(ProcessingEnvironment env) { - this.env = env; - } - - public abstract void verify(Element element, AnnotationMirror annotation, PluginGenerator generator); - - public abstract Class getAnnotationClass(); - - @SuppressWarnings("unchecked") - protected static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { - if (value == null) { - return null; - } - if (expectedType.isArray()) { - ArrayList result = new ArrayList<>(); - List l = (List) value.getValue(); - for (AnnotationValue el : l) { - result.add(resolveAnnotationValue(expectedType.getComponentType(), el)); - } - return (T) result.toArray((Object[]) Array.newInstance(expectedType.getComponentType(), result.size())); - } - Object unboxedValue = value.getValue(); - if (unboxedValue != null) { - if (expectedType == TypeMirror.class && unboxedValue instanceof String) { - /* - * Happens if type is invalid when using the ECJ compiler. The ECJ does not match - * AP-API specification here. - */ - return null; - } - if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { - throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); - } - } - return (T) unboxedValue; - } - - protected static AnnotationValue findAnnotationValue(AnnotationMirror mirror, String name) { - ExecutableElement valueMethod = null; - for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { - if (method.getSimpleName().toString().equals(name)) { - valueMethod = method; - break; - } - } - - if (valueMethod == null) { - return null; - } - - AnnotationValue value = mirror.getElementValues().get(valueMethod); - if (value == null) { - value = valueMethod.getDefaultValue(); - } - - return value; - } - -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/ClassSubstitutionVerifier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/ClassSubstitutionVerifier.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.lang.annotation.Annotation; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.tools.Diagnostic.Kind; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; - -public final class ClassSubstitutionVerifier extends AbstractVerifier { - - private static final String TYPE_VALUE = "value"; - private static final String STRING_VALUE = "className"; - private static final String OPTIONAL = "optional"; - - public ClassSubstitutionVerifier(ProcessingEnvironment env) { - super(env); - } - - @Override - public Class getAnnotationClass() { - return ClassSubstitution.class; - } - - @Override - public void verify(Element element, AnnotationMirror classSubstitution, PluginGenerator generator) { - if (!element.getKind().isClass()) { - assert false : "Element is guaranteed to be a class."; - return; - } - TypeElement type = (TypeElement) element; - - TypeElement substitutionType = resolveOriginalType(env, type, classSubstitution); - if (substitutionType == null) { - return; - } - } - - static TypeElement resolveOriginalType(ProcessingEnvironment env, Element sourceElement, AnnotationMirror classSubstition) { - AnnotationValue typeValue = findAnnotationValue(classSubstition, TYPE_VALUE); - AnnotationValue stringValue = findAnnotationValue(classSubstition, STRING_VALUE); - AnnotationValue optionalValue = findAnnotationValue(classSubstition, OPTIONAL); - - assert typeValue != null && stringValue != null && optionalValue != null; - - TypeMirror type = resolveAnnotationValue(TypeMirror.class, typeValue); - String[] classNames = resolveAnnotationValue(String[].class, stringValue); - boolean optional = resolveAnnotationValue(Boolean.class, optionalValue); - - if (type.getKind() != TypeKind.DECLARED) { - env.getMessager().printMessage(Kind.ERROR, "The provided class must be a declared type.", sourceElement, classSubstition, typeValue); - return null; - } - - if (!classSubstition.getAnnotationType().asElement().equals(((DeclaredType) type).asElement())) { - if (classNames.length != 0) { - String msg = "The usage of value and className is exclusive."; - env.getMessager().printMessage(Kind.ERROR, msg, sourceElement, classSubstition, stringValue); - env.getMessager().printMessage(Kind.ERROR, msg, sourceElement, classSubstition, typeValue); - } - - return (TypeElement) ((DeclaredType) type).asElement(); - } - - if (classNames.length != 0) { - TypeElement typeElement = null; - for (String className : classNames) { - typeElement = env.getElementUtils().getTypeElement(className); - if (typeElement != null) { - break; - } - } - if (typeElement == null && !optional) { - env.getMessager().printMessage(Kind.ERROR, String.format("The class '%s' was not found on the classpath.", stringValue), sourceElement, classSubstition, stringValue); - } - - return typeElement; - } - - if (!optional) { - env.getMessager().printMessage(Kind.ERROR, String.format("No value for '%s' or '%s' provided but required.", TYPE_VALUE, STRING_VALUE), sourceElement, classSubstition); - } - - return null; - } - -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/FoldVerifier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/FoldVerifier.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.lang.annotation.Annotation; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.type.TypeKind; -import javax.tools.Diagnostic.Kind; - -import org.graalvm.compiler.api.replacements.Fold; - -public final class FoldVerifier extends AbstractVerifier { - - public FoldVerifier(ProcessingEnvironment env) { - super(env); - } - - @Override - public Class getAnnotationClass() { - return Fold.class; - } - - @Override - public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) { - if (element.getKind() != ElementKind.METHOD) { - assert false : "Element is guaranteed to be a method."; - return; - } - - ExecutableElement foldMethod = (ExecutableElement) element; - if (foldMethod.getReturnType().getKind() == TypeKind.VOID) { - env.getMessager().printMessage(Kind.ERROR, - String.format("A @%s method must not be void as it won't yield a compile-time constant (the reason for supporting folding!).", Fold.class.getSimpleName()), element, - annotation); - } else if (foldMethod.getModifiers().contains(Modifier.PRIVATE)) { - env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must not be private.", Fold.class.getSimpleName()), element, annotation); - } else { - generator.addPlugin(new GeneratedFoldPlugin(foldMethod)); - } - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedFoldPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedFoldPlugin.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.io.PrintWriter; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.replacements.verifier.InjectedDependencies.WellKnownDependency; - -/** - * Create graph builder plugins for {@link Fold} methods. - */ -public class GeneratedFoldPlugin extends GeneratedPlugin { - - public GeneratedFoldPlugin(ExecutableElement intrinsicMethod) { - super(intrinsicMethod); - } - - private static TypeMirror stringType(ProcessingEnvironment env) { - return env.getElementUtils().getTypeElement("java.lang.String").asType(); - } - - @Override - public void extraImports(Set imports) { - imports.add("jdk.vm.ci.meta.JavaConstant"); - imports.add("jdk.vm.ci.meta.JavaKind"); - imports.add("org.graalvm.compiler.nodes.ConstantNode"); - } - - @Override - protected InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out) { - InjectedDependencies deps = new InjectedDependencies(); - List params = intrinsicMethod.getParameters(); - - int argCount = 0; - Object receiver; - if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { - receiver = intrinsicMethod.getEnclosingElement(); - } else { - receiver = "arg0"; - TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); - constantArgument(env, out, deps, argCount, type.asType(), argCount); - argCount++; - } - - int firstArg = argCount; - for (VariableElement param : params) { - if (param.getAnnotation(InjectedParameter.class) == null) { - constantArgument(env, out, deps, argCount, param.asType(), argCount); - } else { - out.printf(" assert checkInjectedArgument(b, args[%d], targetMethod);\n", argCount); - out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(env, (DeclaredType) param.asType())); - } - argCount++; - } - - Set suppressWarnings = new TreeSet<>(); - if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { - suppressWarnings.add("deprecation"); - } - if (hasRawtypeWarning(intrinsicMethod.getReturnType())) { - suppressWarnings.add("rawtypes"); - } - for (VariableElement param : params) { - if (hasUncheckedWarning(param.asType())) { - suppressWarnings.add("unchecked"); - } - } - if (suppressWarnings.size() > 0) { - out.printf(" @SuppressWarnings({"); - String sep = ""; - for (String suppressWarning : suppressWarnings) { - out.printf("%s\"%s\"", sep, suppressWarning); - sep = ", "; - } - out.printf("})\n"); - } - - out.printf(" %s result = %s.%s(", getErasedType(intrinsicMethod.getReturnType()), receiver, intrinsicMethod.getSimpleName()); - if (argCount > firstArg) { - out.printf("arg%d", firstArg); - for (int i = firstArg + 1; i < argCount; i++) { - out.printf(", arg%d", i); - } - } - out.printf(");\n"); - - TypeMirror returnType = intrinsicMethod.getReturnType(); - switch (returnType.getKind()) { - case BOOLEAN: - out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); - break; - case BYTE: - case SHORT: - case CHAR: - case INT: - out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); - break; - case LONG: - out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); - break; - case FLOAT: - out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); - break; - case DOUBLE: - out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); - break; - case ARRAY: - case TYPEVAR: - case DECLARED: - if (returnType.equals(stringType(env))) { - out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION)); - } else { - out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION)); - } - break; - default: - throw new IllegalArgumentException(returnType.toString()); - } - - out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH)); - out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); - out.printf(" b.notifyReplacedCall(targetMethod, node);\n"); - out.printf(" return true;\n"); - - return deps; - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedNodeIntrinsicPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedNodeIntrinsicPlugin.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.io.PrintWriter; -import java.util.List; -import java.util.Set; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; - -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.InjectedNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; - -/** - * Create graph builder plugins for {@link NodeIntrinsic} methods. - */ -public abstract class GeneratedNodeIntrinsicPlugin extends GeneratedPlugin { - - private final TypeMirror[] signature; - - public GeneratedNodeIntrinsicPlugin(ExecutableElement intrinsicMethod, TypeMirror[] signature) { - super(intrinsicMethod); - this.signature = signature; - } - - private static TypeMirror valueNodeType(ProcessingEnvironment env) { - return env.getElementUtils().getTypeElement("org.graalvm.compiler.nodes.ValueNode").asType(); - } - - protected abstract List getParameters(); - - protected abstract void factoryCall(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argCount); - - @Override - protected InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out) { - InjectedDependencies deps = new InjectedDependencies(); - - List params = getParameters(); - - int idx = 0; - for (; idx < params.size(); idx++) { - VariableElement param = params.get(idx); - if (param.getAnnotation(InjectedNodeParameter.class) == null) { - break; - } - - out.printf(" %s arg%d = %s;\n", param.asType(), idx, deps.use(env, (DeclaredType) param.asType())); - } - - for (int i = 0; i < signature.length; i++, idx++) { - if (intrinsicMethod.getParameters().get(i).getAnnotation(ConstantNodeParameter.class) != null) { - constantArgument(env, out, deps, idx, signature[i], i); - } else { - if (signature[i].equals(valueNodeType(env))) { - out.printf(" ValueNode arg%d = args[%d];\n", idx, i); - } else { - out.printf(" %s arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i); - } - } - } - - factoryCall(env, out, deps, idx); - - return deps; - } - - public static class ConstructorPlugin extends GeneratedNodeIntrinsicPlugin { - - private final ExecutableElement constructor; - - public ConstructorPlugin(ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) { - super(intrinsicMethod, signature); - this.constructor = constructor; - } - - @Override - public void extraImports(Set imports) { - if (intrinsicMethod.getReturnType().getKind() != TypeKind.VOID) { - imports.add("jdk.vm.ci.meta.JavaKind"); - } - } - - @Override - protected List getParameters() { - return constructor.getParameters(); - } - - @Override - protected void factoryCall(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argCount) { - out.printf(" %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement()); - if (argCount > 0) { - out.printf("arg0"); - for (int i = 1; i < argCount; i++) { - out.printf(", arg%d", i); - } - } - out.printf(");\n"); - - if (intrinsicMethod.getReturnType().getKind() == TypeKind.VOID) { - out.printf(" b.add(node);\n"); - } else { - out.printf(" b.addPush(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); - } - out.printf(" return true;\n"); - } - } - - public static class CustomFactoryPlugin extends GeneratedNodeIntrinsicPlugin { - - private final ExecutableElement customFactory; - - public CustomFactoryPlugin(ExecutableElement intrinsicMethod, ExecutableElement customFactory, TypeMirror[] signature) { - super(intrinsicMethod, signature); - this.customFactory = customFactory; - } - - @Override - public void extraImports(Set imports) { - } - - @Override - protected List getParameters() { - List ret = customFactory.getParameters(); - // remove initial GraphBuilderContext and ResolvedJavaMethod parameters - return ret.subList(2, ret.size()); - } - - @Override - protected void factoryCall(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argCount) { - out.printf(" return %s.%s(b, targetMethod", customFactory.getEnclosingElement(), customFactory.getSimpleName()); - for (int i = 0; i < argCount; i++) { - out.printf(", arg%d", i); - } - out.printf(");\n"); - } - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedPlugin.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.io.PrintWriter; -import java.util.Set; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.WildcardType; - -import org.graalvm.compiler.replacements.verifier.InjectedDependencies.Dependency; -import org.graalvm.compiler.replacements.verifier.InjectedDependencies.WellKnownDependency; - -public abstract class GeneratedPlugin { - - protected final ExecutableElement intrinsicMethod; - private boolean needInjectionProvider; - - private String pluginName; - - public GeneratedPlugin(ExecutableElement intrinsicMethod) { - this.intrinsicMethod = intrinsicMethod; - this.needInjectionProvider = false; - this.pluginName = intrinsicMethod.getEnclosingElement().getSimpleName() + "_" + intrinsicMethod.getSimpleName(); - } - - public String getPluginName() { - return pluginName; - } - - public void setPluginName(String pluginName) { - this.pluginName = pluginName; - } - - public void generate(ProcessingEnvironment env, PrintWriter out) { - out.printf(" // class: %s\n", intrinsicMethod.getEnclosingElement()); - out.printf(" // method: %s\n", intrinsicMethod); - out.printf(" // generated-by: %s\n", getClass().getName()); - out.printf(" private static final class %s extends GeneratedInvocationPlugin {\n", pluginName); - out.printf("\n"); - out.printf(" @Override\n"); - out.printf(" public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n"); - InjectedDependencies deps = createExecute(env, out); - out.printf(" }\n"); - - createPrivateMembers(out, deps); - - out.printf(" }\n"); - } - - public void register(PrintWriter out) { - out.printf(" plugins.register(new %s(", pluginName); - if (needInjectionProvider) { - out.printf("injection"); - } - out.printf("), %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName()); - if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { - out.printf(", InvocationPlugin.Receiver.class"); - } - for (VariableElement arg : intrinsicMethod.getParameters()) { - out.printf(", %s.class", getErasedType(arg.asType())); - } - out.printf(");\n"); - } - - public abstract void extraImports(Set imports); - - protected abstract InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out); - - private static TypeMirror resolvedJavaTypeType(ProcessingEnvironment env) { - return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaType").asType(); - } - - static String getErasedType(TypeMirror type) { - switch (type.getKind()) { - case DECLARED: - DeclaredType declared = (DeclaredType) type; - TypeElement element = (TypeElement) declared.asElement(); - return element.getQualifiedName().toString(); - case TYPEVAR: - return getErasedType(((TypeVariable) type).getUpperBound()); - case WILDCARD: - return getErasedType(((WildcardType) type).getExtendsBound()); - case ARRAY: - return getErasedType(((ArrayType) type).getComponentType()) + "[]"; - default: - return type.toString(); - } - } - - static boolean hasRawtypeWarning(TypeMirror type) { - switch (type.getKind()) { - case DECLARED: - DeclaredType declared = (DeclaredType) type; - return declared.getTypeArguments().size() > 0; - case TYPEVAR: - return false; - case WILDCARD: - return false; - case ARRAY: - return hasRawtypeWarning(((ArrayType) type).getComponentType()); - default: - return false; - } - } - - static boolean hasUncheckedWarning(TypeMirror type) { - switch (type.getKind()) { - case DECLARED: - DeclaredType declared = (DeclaredType) type; - for (TypeMirror typeParam : declared.getTypeArguments()) { - if (hasUncheckedWarning(typeParam)) { - return true; - } - } - return false; - case TYPEVAR: - return true; - case WILDCARD: - return ((WildcardType) type).getExtendsBound() != null; - case ARRAY: - return hasUncheckedWarning(((ArrayType) type).getComponentType()); - default: - return false; - } - } - - private void createPrivateMembers(PrintWriter out, InjectedDependencies deps) { - if (!deps.isEmpty()) { - out.printf("\n"); - for (Dependency dep : deps) { - out.printf(" private final %s %s;\n", dep.type, dep.name); - } - - out.printf("\n"); - out.printf(" private %s(InjectionProvider injection) {\n", pluginName); - for (Dependency dep : deps) { - out.printf(" this.%s = %s;\n", dep.name, dep.inject(intrinsicMethod)); - } - out.printf(" }\n"); - - needInjectionProvider = true; - } - } - - protected static String getReturnKind(ExecutableElement method) { - switch (method.getReturnType().getKind()) { - case BOOLEAN: - case BYTE: - case SHORT: - case CHAR: - case INT: - return "Int"; - case LONG: - return "Long"; - case FLOAT: - return "Float"; - case DOUBLE: - return "Double"; - case VOID: - return "Void"; - case ARRAY: - case TYPEVAR: - case DECLARED: - return "Object"; - default: - throw new IllegalArgumentException(method.getReturnType().toString()); - } - } - - protected static void constantArgument(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) { - if (hasRawtypeWarning(type)) { - out.printf(" @SuppressWarnings({\"rawtypes\"})\n"); - } - out.printf(" %s arg%d;\n", getErasedType(type), argIdx); - out.printf(" if (args[%d].isConstant()) {\n", nodeIdx); - if (type.equals(resolvedJavaTypeType(env))) { - out.printf(" arg%d = %s.asJavaType(args[%d].asConstant());\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION), nodeIdx); - } else { - switch (type.getKind()) { - case BOOLEAN: - out.printf(" arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx); - break; - case BYTE: - out.printf(" arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); - break; - case CHAR: - out.printf(" arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); - break; - case SHORT: - out.printf(" arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); - break; - case INT: - out.printf(" arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); - break; - case LONG: - out.printf(" arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx); - break; - case FLOAT: - out.printf(" arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx); - break; - case DOUBLE: - out.printf(" arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx); - break; - case ARRAY: - case DECLARED: - out.printf(" arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), getErasedType(type), nodeIdx); - break; - default: - throw new IllegalArgumentException(type.toString()); - } - } - out.printf(" } else {\n"); - out.printf(" return false;\n"); - out.printf(" }\n"); - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/InjectedDependencies.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/InjectedDependencies.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.util.HashMap; -import java.util.Iterator; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; - -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.replacements.verifier.InjectedDependencies.Dependency; - -public class InjectedDependencies implements Iterable { - - public abstract static class Dependency { - - public final String name; - public final String type; - - private Dependency(String name, String type) { - this.name = name; - this.type = type; - } - - public abstract String inject(ExecutableElement inject); - } - - private static final class InjectedDependency extends Dependency { - - private InjectedDependency(String name, String type) { - super(name, type); - } - - @Override - public String inject(ExecutableElement inject) { - return String.format("injection.getInjectedArgument(%s.class)", type); - } - } - - private static final class InjectedStampDependency extends Dependency { - - private InjectedStampDependency() { - super("stamp", "org.graalvm.compiler.core.common.type.Stamp"); - } - - @Override - public String inject(ExecutableElement inject) { - NodeIntrinsic nodeIntrinsic = inject.getAnnotation(NodeIntrinsic.class); - boolean nonNull = nodeIntrinsic != null && nodeIntrinsic.injectedStampIsNonNull(); - return String.format("injection.getInjectedStamp(%s.class, %s)", GeneratedPlugin.getErasedType(inject.getReturnType()), nonNull); - } - } - - public enum WellKnownDependency { - CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"), - META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"), - INJECTED_STAMP(new InjectedStampDependency()), - SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "org.graalvm.compiler.api.replacements.SnippetReflectionProvider")), - STAMP_PROVIDER("b.getStampProvider()", "org.graalvm.compiler.nodes.spi.StampProvider"), - STRUCTURED_GRAPH("b.getGraph()", "org.graalvm.compiler.nodes.StructuredGraph"); - - private final String expr; - private final String type; - private final Dependency generateMember; - - WellKnownDependency(String expr, String type) { - this.expr = expr; - this.type = type; - this.generateMember = null; - } - - WellKnownDependency(Dependency generateMember) { - this.expr = generateMember.name; - this.type = generateMember.type; - this.generateMember = generateMember; - } - - private TypeMirror getType(ProcessingEnvironment env) { - return env.getElementUtils().getTypeElement(type).asType(); - } - } - - private final HashMap deps; - - public InjectedDependencies() { - deps = new HashMap<>(); - } - - public String use(WellKnownDependency wellKnown) { - if (wellKnown.generateMember != null) { - deps.put(wellKnown.type, wellKnown.generateMember); - } - return wellKnown.expr; - } - - public String use(ProcessingEnvironment env, DeclaredType type) { - for (WellKnownDependency wellKnown : WellKnownDependency.values()) { - if (env.getTypeUtils().isAssignable(wellKnown.getType(env), type)) { - return use(wellKnown); - } - } - - String typeName = type.toString(); - Dependency ret = deps.get(typeName); - if (ret == null) { - ret = new InjectedDependency("injected" + type.asElement().getSimpleName(), typeName); - deps.put(typeName, ret); - } - return ret.name; - } - - @Override - public Iterator iterator() { - return deps.values().iterator(); - } - - public boolean isEmpty() { - return deps.isEmpty(); - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/MethodSubstitutionVerifier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/MethodSubstitutionVerifier.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; - -public final class MethodSubstitutionVerifier extends AbstractVerifier { - - private static final boolean DEBUG = false; - - private static final String ORIGINAL_METHOD_NAME = "value"; - private static final String ORIGINAL_IS_STATIC = "isStatic"; - private static final String ORIGINAL_SIGNATURE = "signature"; - - private static final String ORIGINAL_METHOD_NAME_DEFAULT = ""; - private static final String ORIGINAL_SIGNATURE_DEFAULT = ""; - - public MethodSubstitutionVerifier(ProcessingEnvironment env) { - super(env); - } - - @Override - public Class getAnnotationClass() { - return MethodSubstitution.class; - } - - @SuppressWarnings("unused") - @Override - public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) { - if (element.getKind() != ElementKind.METHOD) { - assert false : "Element is guaranteed to be a method."; - return; - } - ExecutableElement substitutionMethod = (ExecutableElement) element; - TypeElement substitutionType = findEnclosingClass(substitutionMethod); - assert substitutionType != null; - - AnnotationMirror substitutionClassAnnotation = VerifierAnnotationProcessor.findAnnotationMirror(env, substitutionType.getAnnotationMirrors(), ClassSubstitution.class); - if (substitutionClassAnnotation == null) { - env.getMessager().printMessage(Kind.ERROR, String.format("A @%s annotation is required on the enclosing class.", ClassSubstitution.class.getSimpleName()), element, annotation); - return; - } - boolean optional = resolveAnnotationValue(Boolean.class, findAnnotationValue(substitutionClassAnnotation, "optional")); - if (optional) { - return; - } - - TypeElement originalType = ClassSubstitutionVerifier.resolveOriginalType(env, substitutionType, substitutionClassAnnotation); - if (originalType == null) { - env.getMessager().printMessage(Kind.ERROR, String.format("The @%s annotation is invalid on the enclosing class.", ClassSubstitution.class.getSimpleName()), element, annotation); - return; - } - - if (!substitutionMethod.getModifiers().contains(Modifier.STATIC)) { - env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be static.", MethodSubstitution.class.getSimpleName()), element, annotation); - } - - if (substitutionMethod.getModifiers().contains(Modifier.ABSTRACT) || substitutionMethod.getModifiers().contains(Modifier.NATIVE)) { - env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must not be native or abstract.", MethodSubstitution.class.getSimpleName()), element, annotation); - } - - String originalName = originalName(substitutionMethod, annotation); - boolean isStatic = resolveAnnotationValue(Boolean.class, findAnnotationValue(annotation, ORIGINAL_IS_STATIC)); - TypeMirror[] originalSignature = originalSignature(originalType, substitutionMethod, annotation, isStatic); - if (originalSignature == null) { - return; - } - ExecutableElement originalMethod = originalMethod(substitutionMethod, annotation, originalType, originalName, originalSignature, isStatic); - if (DEBUG && originalMethod != null) { - env.getMessager().printMessage(Kind.NOTE, String.format("Found original method %s in type %s.", originalMethod, findEnclosingClass(originalMethod))); - } - } - - private TypeMirror[] originalSignature(TypeElement originalType, ExecutableElement method, AnnotationMirror annotation, boolean isStatic) { - AnnotationValue signatureValue = findAnnotationValue(annotation, ORIGINAL_SIGNATURE); - String signatureString = resolveAnnotationValue(String.class, signatureValue); - List parameters = new ArrayList<>(); - if (signatureString.equals(ORIGINAL_SIGNATURE_DEFAULT)) { - for (int i = 0; i < method.getParameters().size(); i++) { - parameters.add(method.getParameters().get(i).asType()); - } - if (!isStatic) { - if (parameters.isEmpty()) { - env.getMessager().printMessage(Kind.ERROR, "Method signature must be a static method with the 'this' object as its first parameter", method, annotation); - return null; - } else { - TypeMirror thisParam = parameters.remove(0); - if (!isSubtype(originalType.asType(), thisParam)) { - Name thisName = method.getParameters().get(0).getSimpleName(); - env.getMessager().printMessage(Kind.ERROR, String.format("The type of %s must assignable from %s", thisName, originalType), method, annotation); - } - } - } - parameters.add(0, method.getReturnType()); - } else { - try { - APHotSpotSignature signature = new APHotSpotSignature(signatureString); - parameters.add(signature.getReturnType(env)); - for (int i = 0; i < signature.getParameterCount(false); i++) { - parameters.add(signature.getParameterType(env, i)); - } - } catch (Exception e) { - /* - * That's not good practice and should be changed after APHotSpotSignature has - * received a cleanup. - */ - env.getMessager().printMessage(Kind.ERROR, String.format("Parsing the signature failed: %s", e.getMessage() != null ? e.getMessage() : e.toString()), method, annotation, - signatureValue); - return null; - } - } - return parameters.toArray(new TypeMirror[parameters.size()]); - } - - private static String originalName(ExecutableElement substituteMethod, AnnotationMirror substitution) { - String originalMethodName = resolveAnnotationValue(String.class, findAnnotationValue(substitution, ORIGINAL_METHOD_NAME)); - if (originalMethodName.equals(ORIGINAL_METHOD_NAME_DEFAULT)) { - originalMethodName = substituteMethod.getSimpleName().toString(); - } - return originalMethodName; - } - - private ExecutableElement originalMethod(ExecutableElement substitutionMethod, AnnotationMirror substitutionAnnotation, TypeElement originalType, String originalName, - TypeMirror[] originalSignature, boolean isStatic) { - TypeMirror signatureReturnType = originalSignature[0]; - TypeMirror[] signatureParameters = Arrays.copyOfRange(originalSignature, 1, originalSignature.length); - List searchElements; - if (originalName.equals("")) { - searchElements = ElementFilter.constructorsIn(originalType.getEnclosedElements()); - } else { - searchElements = ElementFilter.methodsIn(originalType.getEnclosedElements()); - } - - ExecutableElement originalMethod = null; - outer: for (ExecutableElement searchElement : searchElements) { - if (searchElement.getSimpleName().toString().equals(originalName) && searchElement.getParameters().size() == signatureParameters.length) { - for (int i = 0; i < signatureParameters.length; i++) { - VariableElement parameter = searchElement.getParameters().get(i); - if (!isTypeCompatible(parameter.asType(), signatureParameters[i])) { - continue outer; - } - } - originalMethod = searchElement; - break; - } - } - if (originalMethod == null) { - boolean optional = resolveAnnotationValue(Boolean.class, findAnnotationValue(substitutionAnnotation, "optional")); - if (!optional) { - env.getMessager().printMessage(Kind.ERROR, String.format("Could not find the original method with name '%s' and parameters '%s'.", originalName, Arrays.toString(signatureParameters)), - substitutionMethod, substitutionAnnotation); - } - return null; - } - - if (originalMethod.getModifiers().contains(Modifier.STATIC) != isStatic) { - boolean optional = resolveAnnotationValue(Boolean.class, findAnnotationValue(substitutionAnnotation, "optional")); - if (!optional) { - env.getMessager().printMessage(Kind.ERROR, String.format("The %s element must be set to %s.", ORIGINAL_IS_STATIC, !isStatic), substitutionMethod, substitutionAnnotation); - } - return null; - } - - if (!isTypeCompatible(originalMethod.getReturnType(), signatureReturnType)) { - env.getMessager().printMessage( - Kind.ERROR, - String.format("The return type of the substitution method '%s' must match with the return type of the original method '%s'.", signatureReturnType, - originalMethod.getReturnType()), - substitutionMethod, substitutionAnnotation); - return null; - } - - return originalMethod; - } - - private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { - TypeMirror original = originalType; - TypeMirror substitution = substitutionType; - if (needsErasure(original)) { - original = env.getTypeUtils().erasure(original); - } - if (needsErasure(substitution)) { - substitution = env.getTypeUtils().erasure(substitution); - } - return env.getTypeUtils().isSameType(original, substitution); - } - - /** - * Tests whether one type is a subtype of another. Any type is considered to be a subtype of - * itself. - * - * @param t1 the first type - * @param t2 the second type - * @return {@code true} if and only if the first type is a subtype of the second - */ - private boolean isSubtype(TypeMirror t1, TypeMirror t2) { - TypeMirror t1Erased = t1; - TypeMirror t2Erased = t2; - if (needsErasure(t1Erased)) { - t1Erased = env.getTypeUtils().erasure(t1Erased); - } - if (needsErasure(t2Erased)) { - t2Erased = env.getTypeUtils().erasure(t2Erased); - } - return env.getTypeUtils().isSubtype(t1Erased, t2Erased); - } - - private static boolean needsErasure(TypeMirror typeMirror) { - return typeMirror.getKind() != TypeKind.NONE && typeMirror.getKind() != TypeKind.VOID && !typeMirror.getKind().isPrimitive() && typeMirror.getKind() != TypeKind.OTHER && - typeMirror.getKind() != TypeKind.NULL; - } - - private static TypeElement findEnclosingClass(Element element) { - if (element.getKind().isClass()) { - return (TypeElement) element; - } - - Element enclosing = element.getEnclosingElement(); - while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { - if (enclosing.getKind().isClass()) { - return (TypeElement) enclosing; - } - enclosing = enclosing.getEnclosingElement(); - } - return null; - } - -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/NodeIntrinsicVerifier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/NodeIntrinsicVerifier.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Formatter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; - -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.InjectedNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodeinfo.StructuralInput.MarkerType; - -public final class NodeIntrinsicVerifier extends AbstractVerifier { - - private static final String NODE_CLASS_NAME = "value"; - - private TypeMirror nodeType() { - return env.getElementUtils().getTypeElement("org.graalvm.compiler.graph.Node").asType(); - } - - private TypeMirror stampType() { - return env.getElementUtils().getTypeElement("org.graalvm.compiler.core.common.type.Stamp").asType(); - } - - private TypeMirror valueNodeType() { - return env.getElementUtils().getTypeElement("org.graalvm.compiler.nodes.ValueNode").asType(); - } - - private TypeMirror classType() { - return env.getElementUtils().getTypeElement("java.lang.Class").asType(); - } - - private TypeMirror resolvedJavaTypeType() { - return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaType").asType(); - } - - private TypeMirror resolvedJavaMethodType() { - return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaMethod").asType(); - } - - private TypeMirror structuralInputType() { - return env.getElementUtils().getTypeElement("org.graalvm.compiler.nodeinfo.StructuralInput").asType(); - } - - private TypeMirror graphBuilderContextType() { - return env.getElementUtils().getTypeElement("org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext").asType(); - } - - public NodeIntrinsicVerifier(ProcessingEnvironment env) { - super(env); - } - - @Override - public Class getAnnotationClass() { - return NodeIntrinsic.class; - } - - @Override - public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) { - if (element.getKind() != ElementKind.METHOD) { - assert false : "Element is guaranteed to be a method."; - return; - } - - ExecutableElement intrinsicMethod = (ExecutableElement) element; - if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { - env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be static.", NodeIntrinsic.class.getSimpleName()), element, annotation); - } - if (!intrinsicMethod.getModifiers().contains(Modifier.NATIVE)) { - env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be native.", NodeIntrinsic.class.getSimpleName()), element, annotation); - } - - TypeMirror nodeClassMirror = resolveAnnotationValue(TypeMirror.class, findAnnotationValue(annotation, NODE_CLASS_NAME)); - TypeElement nodeClass = (TypeElement) env.getTypeUtils().asElement(nodeClassMirror); - if (nodeClass.getSimpleName().contentEquals(NodeIntrinsic.class.getSimpleName())) { - // default value - Element enclosingElement = intrinsicMethod.getEnclosingElement(); - while (enclosingElement != null && enclosingElement.getKind() != ElementKind.CLASS) { - enclosingElement = enclosingElement.getEnclosingElement(); - } - if (enclosingElement != null) { - nodeClass = (TypeElement) enclosingElement; - } - } - - TypeMirror returnType = intrinsicMethod.getReturnType(); - if (returnType instanceof TypeVariable) { - env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic cannot have a generic return type.", element, annotation); - } - - boolean injectedStampIsNonNull = intrinsicMethod.getAnnotation(NodeIntrinsic.class).injectedStampIsNonNull(); - - if (returnType.getKind() == TypeKind.VOID) { - for (VariableElement parameter : intrinsicMethod.getParameters()) { - if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { - env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic with an injected Stamp parameter cannot have a void return type.", element, annotation); - break; - } - } - } - - TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); - Map nonMatches = new HashMap<>(); - List factories = findIntrinsifyFactoryMethod(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); - List constructors = Collections.emptyList(); - if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { - if (factories.isEmpty()) { - env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make a node intrinsic for an abstract class %s.", nodeClass.getSimpleName()), element, annotation); - } - } else if (!isNodeType(nodeClass)) { - if (factories.isEmpty()) { - env.getMessager().printMessage(Kind.ERROR, String.format("%s is not a subclass of %s.", nodeClass.getSimpleName(), nodeType()), element, annotation); - } - } else { - TypeMirror ret = returnType; - if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { - checkInputType(nodeClass, ret, element, annotation); - } - - constructors = findConstructors(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); - } - Formatter msg = new Formatter(); - if (factories.size() > 1) { - msg.format("Found more than one factory in %s matching node intrinsic:", nodeClass); - for (ExecutableElement candidate : factories) { - msg.format("%n %s", candidate); - } - env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); - } else if (constructors.size() > 1) { - msg.format("Found more than one constructor in %s matching node intrinsic:", nodeClass); - for (ExecutableElement candidate : constructors) { - msg.format("%n %s", candidate); - } - env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); - } else if (factories.size() == 1) { - generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, factories.get(0), constructorSignature)); - } else if (constructors.size() == 1) { - generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructors.get(0), constructorSignature)); - } else { - msg.format("Could not find any factories or constructors in %s matching node intrinsic", nodeClass); - if (!nonMatches.isEmpty()) { - msg.format("%nFactories and constructors that failed to match:"); - for (Map.Entry e : nonMatches.entrySet()) { - msg.format("%n %s: %s", e.getKey(), e.getValue()); - } - } - env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); - } - } - - private void checkInputType(TypeElement nodeClass, TypeMirror returnType, Element element, AnnotationMirror annotation) { - InputType inputType = getInputType(returnType, element, annotation); - if (inputType != InputType.Value) { - boolean allowed = false; - InputType[] allowedTypes = nodeClass.getAnnotation(NodeInfo.class).allowedUsageTypes(); - for (InputType allowedType : allowedTypes) { - if (inputType == allowedType) { - allowed = true; - break; - } - } - if (!allowed) { - env.getMessager().printMessage(Kind.ERROR, String.format("@NodeIntrinsic returns input type %s, but only %s is allowed.", inputType, Arrays.toString(allowedTypes)), element, - annotation); - } - } - } - - private InputType getInputType(TypeMirror type, Element element, AnnotationMirror annotation) { - TypeElement current = (TypeElement) env.getTypeUtils().asElement(type); - while (current != null) { - MarkerType markerType = current.getAnnotation(MarkerType.class); - if (markerType != null) { - return markerType.value(); - } - - current = (TypeElement) env.getTypeUtils().asElement(current.getSuperclass()); - } - - env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is a subclass of StructuralInput, but isn't annotated with @MarkerType.", type), element, annotation); - return InputType.Value; - } - - private boolean isNodeType(TypeElement nodeClass) { - return env.getTypeUtils().isSubtype(nodeClass.asType(), nodeType()); - } - - private TypeMirror[] constructorSignature(ExecutableElement method) { - TypeMirror[] parameters = new TypeMirror[method.getParameters().size()]; - for (int i = 0; i < method.getParameters().size(); i++) { - VariableElement parameter = method.getParameters().get(i); - if (parameter.getAnnotation(ConstantNodeParameter.class) == null) { - parameters[i] = valueNodeType(); - } else { - TypeMirror type = parameter.asType(); - if (isTypeCompatible(type, classType())) { - type = resolvedJavaTypeType(); - } - parameters[i] = type; - } - } - return parameters; - } - - private List findConstructors(TypeElement nodeClass, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { - List constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements()); - List found = new ArrayList<>(constructors.size()); - for (ExecutableElement constructor : constructors) { - if (matchSignature(0, constructor, signature, nonMatches, requiresInjectedStamp)) { - found.add(constructor); - } - } - return found; - } - - private List findIntrinsifyFactoryMethod(TypeElement nodeClass, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { - List methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); - List found = new ArrayList<>(methods.size()); - for (ExecutableElement method : methods) { - if (!method.getSimpleName().toString().equals("intrinsify")) { - continue; - } - - if (method.getParameters().size() < 2) { - continue; - } - - VariableElement firstArg = method.getParameters().get(0); - if (!isTypeCompatible(firstArg.asType(), graphBuilderContextType())) { - continue; - } - - VariableElement secondArg = method.getParameters().get(1); - if (!isTypeCompatible(secondArg.asType(), resolvedJavaMethodType())) { - continue; - } - - if (method.getReturnType().getKind() != TypeKind.BOOLEAN) { - continue; - } - - if (matchSignature(2, method, signature, nonMatches, requiresInjectedStamp)) { - found.add(method); - } - } - return found; - } - - private boolean matchSignature(int numSkippedParameters, ExecutableElement method, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { - int sIdx = 0; - int cIdx = numSkippedParameters; - boolean missingStampArgument = requiresInjectedStamp; - while (cIdx < method.getParameters().size()) { - VariableElement parameter = method.getParameters().get(cIdx++); - TypeMirror paramType = parameter.asType(); - if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { - if (missingStampArgument && env.getTypeUtils().isSameType(paramType, stampType())) { - missingStampArgument = false; - } - // skip injected parameters - continue; - } - if (missingStampArgument) { - nonMatches.put(method, String.format("missing injected %s argument", stampType())); - return false; - } - - if (cIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { - // last argument of constructor is varargs, match remaining intrinsic arguments - TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); - while (sIdx < signature.length) { - if (!isTypeCompatible(varargsType, signature[sIdx++])) { - nonMatches.put(method, String.format("the types of argument %d are incompatible: %s != %s", sIdx, varargsType, signature[sIdx - 1])); - return false; - } - } - } else if (sIdx >= signature.length) { - // too many arguments in intrinsic method - nonMatches.put(method, "too many arguments"); - return false; - } else if (!isTypeCompatible(paramType, signature[sIdx++])) { - nonMatches.put(method, String.format("the type of argument %d is incompatible: %s != %s", sIdx, paramType, signature[sIdx - 1])); - return false; - } - } - if (missingStampArgument) { - nonMatches.put(method, String.format("missing injected %s argument", stampType())); - return false; - } - - if (sIdx != signature.length) { - nonMatches.put(method, "not enough arguments"); - return false; - } - return true; - } - - private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { - TypeMirror original = originalType; - TypeMirror substitution = substitutionType; - if (needsErasure(original)) { - original = env.getTypeUtils().erasure(original); - } - if (needsErasure(substitution)) { - substitution = env.getTypeUtils().erasure(substitution); - } - return env.getTypeUtils().isSameType(original, substitution); - } - - private static boolean needsErasure(TypeMirror typeMirror) { - return typeMirror.getKind() != TypeKind.NONE && typeMirror.getKind() != TypeKind.VOID && !typeMirror.getKind().isPrimitive() && typeMirror.getKind() != TypeKind.OTHER && - typeMirror.getKind() != TypeKind.NULL; - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/PluginGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/PluginGenerator.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Function; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.WildcardType; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; - -public class PluginGenerator { - - private final Map> plugins; - - public PluginGenerator() { - this.plugins = new HashMap<>(); - } - - public void addPlugin(GeneratedPlugin plugin) { - Element topLevel = getTopLevelClass(plugin.intrinsicMethod); - List list = plugins.get(topLevel); - if (list == null) { - list = new ArrayList<>(); - plugins.put(topLevel, list); - } - list.add(plugin); - } - - public void generateAll(ProcessingEnvironment env) { - for (Entry> entry : plugins.entrySet()) { - disambiguateNames(entry.getValue()); - createPluginFactory(env, entry.getKey(), entry.getValue()); - } - } - - private static Element getTopLevelClass(Element element) { - Element prev = element; - Element enclosing = element.getEnclosingElement(); - while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { - prev = enclosing; - enclosing = enclosing.getEnclosingElement(); - } - return prev; - } - - private static void disambiguateWith(List plugins, Function genName) { - plugins.sort(Comparator.comparing(GeneratedPlugin::getPluginName)); - - GeneratedPlugin current = plugins.get(0); - String currentName = current.getPluginName(); - - for (int i = 1; i < plugins.size(); i++) { - GeneratedPlugin next = plugins.get(i); - if (currentName.equals(next.getPluginName())) { - if (current != null) { - current.setPluginName(genName.apply(current)); - current = null; - } - next.setPluginName(genName.apply(next)); - } else { - current = next; - currentName = current.getPluginName(); - } - } - } - - private static void appendSimpleTypeName(StringBuilder ret, TypeMirror type) { - switch (type.getKind()) { - case DECLARED: - DeclaredType declared = (DeclaredType) type; - TypeElement element = (TypeElement) declared.asElement(); - ret.append(element.getSimpleName()); - break; - case TYPEVAR: - appendSimpleTypeName(ret, ((TypeVariable) type).getUpperBound()); - break; - case WILDCARD: - appendSimpleTypeName(ret, ((WildcardType) type).getExtendsBound()); - break; - case ARRAY: - appendSimpleTypeName(ret, ((ArrayType) type).getComponentType()); - ret.append("Array"); - break; - default: - ret.append(type); - } - } - - private static void disambiguateNames(List plugins) { - // if we have more than one method with the same name, disambiguate with the argument types - disambiguateWith(plugins, plugin -> { - StringBuilder ret = new StringBuilder(plugin.getPluginName()); - for (VariableElement param : plugin.intrinsicMethod.getParameters()) { - ret.append('_'); - appendSimpleTypeName(ret, param.asType()); - } - return ret.toString(); - }); - - // since we're using simple names for argument types, we could still have a collision - disambiguateWith(plugins, new Function() { - - private int idx = 0; - - @Override - public String apply(GeneratedPlugin plugin) { - return plugin.getPluginName() + "_" + (idx++); - } - }); - } - - private static void createPluginFactory(ProcessingEnvironment env, Element topLevelClass, List plugins) { - PackageElement pkg = (PackageElement) topLevelClass.getEnclosingElement(); - - String genClassName = "PluginFactory_" + topLevelClass.getSimpleName(); - - try { - JavaFileObject factory = env.getFiler().createSourceFile(pkg.getQualifiedName() + "." + genClassName, topLevelClass); - try (PrintWriter out = new PrintWriter(factory.openWriter())) { - out.printf("// CheckStyle: stop header check\n"); - out.printf("// CheckStyle: stop line length check\n"); - out.printf("// GENERATED CONTENT - DO NOT EDIT\n"); - out.printf("// GENERATORS: %s, %s\n", VerifierAnnotationProcessor.class.getName(), PluginGenerator.class.getName()); - out.printf("package %s;\n", pkg.getQualifiedName()); - out.printf("\n"); - createImports(out, plugins); - out.printf("\n"); - out.printf("@ServiceProvider(NodeIntrinsicPluginFactory.class)\n"); - out.printf("public class %s implements NodeIntrinsicPluginFactory {\n", genClassName); - for (GeneratedPlugin plugin : plugins) { - out.printf("\n"); - plugin.generate(env, out); - } - out.printf("\n"); - createPluginFactoryMethod(out, plugins); - out.printf("}\n"); - } - } catch (IOException e) { - env.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); - } - } - - protected static void createImports(PrintWriter out, List plugins) { - out.printf("import jdk.vm.ci.meta.ResolvedJavaMethod;\n"); - out.printf("import org.graalvm.compiler.serviceprovider.ServiceProvider;\n"); - out.printf("\n"); - out.printf("import org.graalvm.compiler.nodes.ValueNode;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;\n"); - - HashSet extra = new HashSet<>(); - for (GeneratedPlugin plugin : plugins) { - plugin.extraImports(extra); - } - if (!extra.isEmpty()) { - out.printf("\n"); - for (String i : extra) { - out.printf("import %s;\n", i); - } - } - } - - private static void createPluginFactoryMethod(PrintWriter out, List plugins) { - out.printf(" @Override\n"); - out.printf(" public void registerPlugins(InvocationPlugins plugins, InjectionProvider injection) {\n"); - for (GeneratedPlugin plugin : plugins) { - plugin.register(out); - } - out.printf(" }\n"); - } -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/VerifierAnnotationProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/VerifierAnnotationProcessor.java Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.verifier; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; - -public class VerifierAnnotationProcessor extends AbstractProcessor { - - private List verifiers; - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latest(); - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (!roundEnv.processingOver()) { - PluginGenerator generator = new PluginGenerator(); - for (AbstractVerifier verifier : getVerifiers()) { - Class annotationClass = verifier.getAnnotationClass(); - for (Element e : roundEnv.getElementsAnnotatedWith(annotationClass)) { - AnnotationMirror annotationMirror = findAnnotationMirror(processingEnv, e.getAnnotationMirrors(), annotationClass); - if (annotationMirror == null) { - assert false : "Annotation mirror always expected."; - continue; - } - verifier.verify(e, annotationMirror, generator); - } - } - - generator.generateAll(processingEnv); - } - return false; - } - - public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { - TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); - for (AnnotationMirror mirror : mirrors) { - DeclaredType annotationType = mirror.getAnnotationType(); - TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); - if (actualAnnotationType.equals(expectedAnnotationType)) { - return mirror; - } - } - return null; - } - - public List getVerifiers() { - /* - * Initialized lazily to fail(CNE) when the processor is invoked and not when it is created. - */ - if (verifiers == null) { - assert this.processingEnv != null : "ProcessingEnv must be initialized before calling getVerifiers."; - verifiers = new ArrayList<>(); - verifiers.add(new ClassSubstitutionVerifier(this.processingEnv)); - verifiers.add(new MethodSubstitutionVerifier(this.processingEnv)); - verifiers.add(new NodeIntrinsicVerifier(this.processingEnv)); - verifiers.add(new FoldVerifier(this.processingEnv)); - } - return verifiers; - } - - @Override - public Set getSupportedAnnotationTypes() { - Set annotationTypes = new HashSet<>(); - for (AbstractVerifier verifier : getVerifiers()) { - annotationTypes.add(verifier.getAnnotationClass().getCanonicalName()); - } - return annotationTypes; - } - -} diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu May 31 13:39:26 2018 -0700 @@ -41,6 +41,7 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.IntegerStamp; @@ -84,6 +85,7 @@ import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.JavaReadNode; import org.graalvm.compiler.nodes.extended.JavaWriteNode; +import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; @@ -109,7 +111,9 @@ import org.graalvm.compiler.nodes.java.RawMonitorEnterNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; +import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; @@ -156,6 +160,7 @@ protected final ForeignCallsProvider foreignCalls; protected final TargetDescription target; private final boolean useCompressedOops; + private final ResolvedJavaType objectArrayType; private BoxingSnippets.Templates boxingSnippets; private ConstantStringIndexOfSnippets.Templates indexOfSnippets; @@ -165,6 +170,7 @@ this.foreignCalls = foreignCalls; this.target = target; this.useCompressedOops = useCompressedOops; + this.objectArrayType = metaAccess.lookupJavaType(Object[].class); } public void initialize(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) { @@ -178,57 +184,64 @@ } @Override + @SuppressWarnings("try") public void lower(Node n, LoweringTool tool) { assert n instanceof Lowerable; StructuredGraph graph = (StructuredGraph) n.graph(); - if (n instanceof LoadFieldNode) { - lowerLoadFieldNode((LoadFieldNode) n, tool); - } else if (n instanceof StoreFieldNode) { - lowerStoreFieldNode((StoreFieldNode) n, tool); - } else if (n instanceof LoadIndexedNode) { - lowerLoadIndexedNode((LoadIndexedNode) n, tool); - } else if (n instanceof StoreIndexedNode) { - lowerStoreIndexedNode((StoreIndexedNode) n, tool); - } else if (n instanceof ArrayLengthNode) { - lowerArrayLengthNode((ArrayLengthNode) n, tool); - } else if (n instanceof LoadHubNode) { - lowerLoadHubNode((LoadHubNode) n, tool); - } else if (n instanceof MonitorEnterNode) { - lowerMonitorEnterNode((MonitorEnterNode) n, tool, graph); - } else if (n instanceof UnsafeCompareAndSwapNode) { - lowerCompareAndSwapNode((UnsafeCompareAndSwapNode) n); - } else if (n instanceof AtomicReadAndWriteNode) { - lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); - } else if (n instanceof RawLoadNode) { - lowerUnsafeLoadNode((RawLoadNode) n, tool); - } else if (n instanceof UnsafeMemoryLoadNode) { - lowerUnsafeMemoryLoadNode((UnsafeMemoryLoadNode) n); - } else if (n instanceof RawStoreNode) { - lowerUnsafeStoreNode((RawStoreNode) n); - } else if (n instanceof UnsafeMemoryStoreNode) { - lowerUnsafeMemoryStoreNode((UnsafeMemoryStoreNode) n); - } else if (n instanceof JavaReadNode) { - lowerJavaReadNode((JavaReadNode) n); - } else if (n instanceof JavaWriteNode) { - lowerJavaWriteNode((JavaWriteNode) n); - } else if (n instanceof CommitAllocationNode) { - lowerCommitAllocationNode((CommitAllocationNode) n, tool); - } else if (n instanceof BoxNode) { - boxingSnippets.lower((BoxNode) n, tool); - } else if (n instanceof UnboxNode) { - boxingSnippets.lower((UnboxNode) n, tool); - } else if (n instanceof VerifyHeapNode) { - lowerVerifyHeap((VerifyHeapNode) n); - } else if (n instanceof UnaryMathIntrinsicNode) { - lowerUnaryMath((UnaryMathIntrinsicNode) n, tool); - } else if (n instanceof BinaryMathIntrinsicNode) { - lowerBinaryMath((BinaryMathIntrinsicNode) n, tool); - } else if (n instanceof StringIndexOfNode) { - lowerIndexOf((StringIndexOfNode) n); - } else if (n instanceof UnpackEndianHalfNode) { - lowerSecondHalf((UnpackEndianHalfNode) n); - } else { - throw GraalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + try (DebugCloseable context = n.withNodeSourcePosition()) { + if (n instanceof LoadFieldNode) { + lowerLoadFieldNode((LoadFieldNode) n, tool); + } else if (n instanceof StoreFieldNode) { + lowerStoreFieldNode((StoreFieldNode) n, tool); + } else if (n instanceof LoadIndexedNode) { + lowerLoadIndexedNode((LoadIndexedNode) n, tool); + } else if (n instanceof StoreIndexedNode) { + lowerStoreIndexedNode((StoreIndexedNode) n, tool); + } else if (n instanceof ArrayLengthNode) { + lowerArrayLengthNode((ArrayLengthNode) n, tool); + } else if (n instanceof LoadHubNode) { + lowerLoadHubNode((LoadHubNode) n, tool); + } else if (n instanceof LoadArrayComponentHubNode) { + lowerLoadArrayComponentHubNode((LoadArrayComponentHubNode) n); + } else if (n instanceof MonitorEnterNode) { + lowerMonitorEnterNode((MonitorEnterNode) n, tool, graph); + } else if (n instanceof UnsafeCompareAndSwapNode) { + lowerCompareAndSwapNode((UnsafeCompareAndSwapNode) n); + } else if (n instanceof UnsafeCompareAndExchangeNode) { + lowerCompareAndExchangeNode((UnsafeCompareAndExchangeNode) n); + } else if (n instanceof AtomicReadAndWriteNode) { + lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); + } else if (n instanceof RawLoadNode) { + lowerUnsafeLoadNode((RawLoadNode) n, tool); + } else if (n instanceof UnsafeMemoryLoadNode) { + lowerUnsafeMemoryLoadNode((UnsafeMemoryLoadNode) n); + } else if (n instanceof RawStoreNode) { + lowerUnsafeStoreNode((RawStoreNode) n); + } else if (n instanceof UnsafeMemoryStoreNode) { + lowerUnsafeMemoryStoreNode((UnsafeMemoryStoreNode) n); + } else if (n instanceof JavaReadNode) { + lowerJavaReadNode((JavaReadNode) n); + } else if (n instanceof JavaWriteNode) { + lowerJavaWriteNode((JavaWriteNode) n); + } else if (n instanceof CommitAllocationNode) { + lowerCommitAllocationNode((CommitAllocationNode) n, tool); + } else if (n instanceof BoxNode) { + boxingSnippets.lower((BoxNode) n, tool); + } else if (n instanceof UnboxNode) { + boxingSnippets.lower((UnboxNode) n, tool); + } else if (n instanceof VerifyHeapNode) { + lowerVerifyHeap((VerifyHeapNode) n); + } else if (n instanceof UnaryMathIntrinsicNode) { + lowerUnaryMath((UnaryMathIntrinsicNode) n, tool); + } else if (n instanceof BinaryMathIntrinsicNode) { + lowerBinaryMath((BinaryMathIntrinsicNode) n, tool); + } else if (n instanceof StringIndexOfNode) { + lowerIndexOf((StringIndexOfNode) n); + } else if (n instanceof UnpackEndianHalfNode) { + lowerSecondHalf((UnpackEndianHalfNode) n); + } else { + throw GraalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + } } } @@ -445,7 +458,7 @@ JavaKind elementKind = storeIndexed.elementKind(); LogicNode condition = null; - if (elementKind == JavaKind.Object && !StampTool.isPointerAlwaysNull(value)) { + if (storeIndexed.getStoreCheck() == null && elementKind == JavaKind.Object && !StampTool.isPointerAlwaysNull(value)) { /* Array store check. */ TypeReference arrayType = StampTool.typeReferenceOrNull(array); if (arrayType != null && arrayType.isExact()) { @@ -510,6 +523,12 @@ loadHub.replaceAtUsagesAndDelete(hub); } + protected void lowerLoadArrayComponentHubNode(LoadArrayComponentHubNode loadHub) { + StructuredGraph graph = loadHub.graph(); + ValueNode hub = createReadArrayComponentHub(graph, loadHub.getValue(), loadHub); + graph.replaceFixed(loadHub, hub); + } + protected void lowerMonitorEnterNode(MonitorEnterNode monitorEnter, LoweringTool tool, StructuredGraph graph) { ValueNode object = createNullCheckedValue(monitorEnter.object(), monitorEnter, tool); ValueNode hub = graph.addOrUnique(LoadHubNode.create(object, tool.getStampProvider(), tool.getMetaAccess(), tool.getConstantReflection())); @@ -527,12 +546,28 @@ ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset())); - BarrierType barrierType = storeBarrierType(cas.object(), expectedValue); + BarrierType barrierType = guessStoreBarrierType(cas.object(), expectedValue); LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, barrierType)); atomicNode.setStateAfter(cas.stateAfter()); graph.replaceFixedWithFixed(cas, atomicNode); } + protected void lowerCompareAndExchangeNode(UnsafeCompareAndExchangeNode cas) { + StructuredGraph graph = cas.graph(); + JavaKind valueKind = cas.getValueKind(); + + ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected()); + ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); + + AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset())); + BarrierType barrierType = guessStoreBarrierType(cas.object(), expectedValue); + ValueCompareAndSwapNode atomicNode = graph.add(new ValueCompareAndSwapNode(address, expectedValue, newValue, cas.getLocationIdentity(), barrierType)); + ValueNode coercedNode = implicitLoadConvert(graph, valueKind, atomicNode, true); + atomicNode.setStateAfter(cas.stateAfter()); + cas.replaceAtUsages(coercedNode); + graph.replaceFixedWithFixed(cas, atomicNode); + } + protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { StructuredGraph graph = n.graph(); JavaKind valueKind = n.getValueKind(); @@ -540,8 +575,9 @@ ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset())); - BarrierType barrierType = storeBarrierType(n.object(), n.newValue()); - LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, barrierType)); + BarrierType barrierType = guessStoreBarrierType(n.object(), n.newValue()); + LIRKind lirAccessKind = LIRKind.fromJavaKind(target.arch, valueKind); + LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, lirAccessKind, barrierType)); memoryRead.setStateAfter(n.stateAfter()); ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); @@ -687,85 +723,87 @@ int valuePos = 0; for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - AbstractNewObjectNode newObject; - try (DebugCloseable nsp = virtual.withNodeSourcePosition()) { + try (DebugCloseable nsp = graph.withNodeSourcePosition(virtual)) { + int entryCount = virtual.entryCount(); + AbstractNewObjectNode newObject; if (virtual instanceof VirtualInstanceNode) { newObject = graph.add(createNewInstanceFromVirtual(virtual)); } else { newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph))); } - } - recursiveLowerings.add(newObject); - graph.addBeforeFixed(commit, newObject); - allocations[objIndex] = newObject; - for (int i = 0; i < entryCount; i++) { - ValueNode value = commit.getValues().get(valuePos); - if (value instanceof VirtualObjectNode) { - value = allocations[commit.getVirtualObjects().indexOf(value)]; - } - if (value == null) { - omittedValues.set(valuePos); - } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - // Constant.illegal is always the defaultForKind, so it is skipped - JavaKind valueKind = value.getStackKind(); - JavaKind entryKind = virtual.entryKind(i); + + recursiveLowerings.add(newObject); + graph.addBeforeFixed(commit, newObject); + allocations[objIndex] = newObject; + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos); + if (value instanceof VirtualObjectNode) { + value = allocations[commit.getVirtualObjects().indexOf(value)]; + } + if (value == null) { + omittedValues.set(valuePos); + } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + // Constant.illegal is always the defaultForKind, so it is skipped + JavaKind valueKind = value.getStackKind(); + JavaKind entryKind = virtual.entryKind(i); - // Truffle requires some leniency in terms of what can be put where: - assert valueKind.getStackKind() == entryKind.getStackKind() || - (valueKind == JavaKind.Long || valueKind == JavaKind.Double || (valueKind == JavaKind.Int && virtual instanceof VirtualArrayNode)); - AddressNode address = null; - BarrierType barrierType = null; - if (virtual instanceof VirtualInstanceNode) { - ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); - long offset = fieldOffset(field); - if (offset >= 0) { - address = createOffsetAddress(graph, newObject, offset); - barrierType = fieldInitializationBarrier(entryKind); + // Truffle requires some leniency in terms of what can be put where: + assert valueKind.getStackKind() == entryKind.getStackKind() || + (valueKind == JavaKind.Long || valueKind == JavaKind.Double || (valueKind == JavaKind.Int && virtual instanceof VirtualArrayNode)); + AddressNode address = null; + BarrierType barrierType = null; + if (virtual instanceof VirtualInstanceNode) { + ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); + long offset = fieldOffset(field); + if (offset >= 0) { + address = createOffsetAddress(graph, newObject, offset); + barrierType = fieldInitializationBarrier(entryKind); + } + } else { + address = createOffsetAddress(graph, newObject, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind)); + barrierType = arrayInitializationBarrier(entryKind); } - } else { - address = createOffsetAddress(graph, newObject, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind)); - barrierType = arrayInitializationBarrier(entryKind); + if (address != null) { + WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType); + graph.addAfterFixed(newObject, graph.add(write)); + } } - if (address != null) { - WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType); - graph.addAfterFixed(newObject, graph.add(write)); - } + valuePos++; } - valuePos++; - } } valuePos = 0; for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - ValueNode newObject = allocations[objIndex]; - for (int i = 0; i < entryCount; i++) { - if (omittedValues.get(valuePos)) { - ValueNode value = commit.getValues().get(valuePos); - assert value instanceof VirtualObjectNode; - ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; - if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { - assert virtual.entryKind(i) == JavaKind.Object && allocValue.getStackKind() == JavaKind.Object; - AddressNode address; - BarrierType barrierType; - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; - address = createFieldAddress(graph, newObject, virtualInstance.field(i)); - barrierType = BarrierType.IMPRECISE; - } else { - address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph)); - barrierType = BarrierType.PRECISE; - } - if (address != null) { - WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType); - graph.addBeforeFixed(commit, graph.add(write)); + try (DebugCloseable nsp = graph.withNodeSourcePosition(virtual)) { + int entryCount = virtual.entryCount(); + ValueNode newObject = allocations[objIndex]; + for (int i = 0; i < entryCount; i++) { + if (omittedValues.get(valuePos)) { + ValueNode value = commit.getValues().get(valuePos); + assert value instanceof VirtualObjectNode; + ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; + if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { + assert virtual.entryKind(i) == JavaKind.Object && allocValue.getStackKind() == JavaKind.Object; + AddressNode address; + BarrierType barrierType; + if (virtual instanceof VirtualInstanceNode) { + VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; + address = createFieldAddress(graph, newObject, virtualInstance.field(i)); + barrierType = BarrierType.IMPRECISE; + } else { + address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph)); + barrierType = BarrierType.PRECISE; + } + if (address != null) { + WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType); + graph.addBeforeFixed(commit, graph.add(write)); + } } } + valuePos++; } - valuePos++; } } @@ -776,6 +814,7 @@ recursiveLowering.lower(tool); } } + } public NewInstanceNode createNewInstanceFromVirtual(VirtualObjectNode virtual) { @@ -890,20 +929,22 @@ return entryKind == JavaKind.Object ? BarrierType.PRECISE : BarrierType.NONE; } - private static BarrierType unsafeStoreBarrierType(RawStoreNode store) { + private BarrierType unsafeStoreBarrierType(RawStoreNode store) { if (!store.needsBarrier()) { return BarrierType.NONE; } - return storeBarrierType(store.object(), store.value()); + return guessStoreBarrierType(store.object(), store.value()); } - private static BarrierType storeBarrierType(ValueNode object, ValueNode value) { + private BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) { ResolvedJavaType type = StampTool.typeOrNull(object); - if (type != null && !type.isArray()) { + // Array types must use a precise barrier, so if the type is unknown or is a supertype + // of Object[] then treat it as an array. + if (type == null || type.isArray() || type.isAssignableFrom(objectArrayType)) { + return BarrierType.PRECISE; + } else { return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; } } return BarrierType.NONE; @@ -1030,6 +1071,10 @@ protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor); protected GuardingNode getBoundsCheck(AccessIndexedNode n, ValueNode array, LoweringTool tool) { + if (n.getBoundsCheck() != null) { + return n.getBoundsCheck(); + } + StructuredGraph graph = n.graph(); ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection()); if (arrayLength == null) { @@ -1049,7 +1094,7 @@ if (StampTool.isPointerNonNull(object)) { return null; } - return tool.createGuard(before, before.graph().unique(IsNullNode.create(object)), NullCheckException, InvalidateReprofile, JavaConstant.NULL_POINTER, true); + return tool.createGuard(before, before.graph().unique(IsNullNode.create(object)), NullCheckException, InvalidateReprofile, JavaConstant.NULL_POINTER, true, null); } protected ValueNode createNullCheckedValue(ValueNode object, FixedNode before, LoweringTool tool) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Thu May 31 13:39:26 2018 -0700 @@ -359,7 +359,7 @@ calleeGraph.setTrackNodeSourcePosition(); } IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING); - GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, + GraphBuilderPhase.Instance instance = createGraphBuilderInstance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, initialReplacementContext); instance.apply(calleeGraph); @@ -371,6 +371,11 @@ InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase); } + protected GraphBuilderPhase.Instance createGraphBuilderInstance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, + ConstantFieldProvider constantFieldProvider, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { + return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); + } + protected void pushStructure(Structure structure) { structures.add(structure); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Thu May 31 13:39:26 2018 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.replacements; +import java.net.URI; import static org.graalvm.compiler.debug.GraalError.unimplemented; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; @@ -34,6 +35,7 @@ import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.Equivalence; +import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.PermanentBailoutException; @@ -46,6 +48,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.SourceLanguagePosition; @@ -78,6 +81,7 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; @@ -157,7 +161,7 @@ protected final int inliningDepth; protected final ValueNode[] arguments; - private final SourceLanguagePosition sourceLanguagePosition; + private SourceLanguagePosition sourceLanguagePosition = UnresolvedSourceLanguagePosition.INSTANCE; protected FrameState outerState; protected FrameState exceptionState; @@ -173,13 +177,6 @@ this.invokeData = invokeData; this.inliningDepth = inliningDepth; this.arguments = arguments; - SourceLanguagePosition position = null; - if (arguments != null && method.hasReceiver() && arguments.length > 0 && arguments[0].isJavaConstant()) { - JavaConstant constantArgument = arguments[0].asJavaConstant(); - position = sourceLanguagePositionProvider.getPosition(constantArgument); - } - this.sourceLanguagePosition = position; - } @Override @@ -201,13 +198,61 @@ callerBytecodePosition = invokePosition; } if (position != null) { - return position.addCaller(caller.sourceLanguagePosition, callerBytecodePosition); + return position.addCaller(caller.resolveSourceLanguagePosition(), callerBytecodePosition); } - if (caller.sourceLanguagePosition != null && callerBytecodePosition != null) { - return new NodeSourcePosition(caller.sourceLanguagePosition, callerBytecodePosition.getCaller(), callerBytecodePosition.getMethod(), callerBytecodePosition.getBCI()); + final SourceLanguagePosition pos = caller.resolveSourceLanguagePosition(); + if (pos != null && callerBytecodePosition != null) { + return new NodeSourcePosition(pos, callerBytecodePosition.getCaller(), callerBytecodePosition.getMethod(), callerBytecodePosition.getBCI()); } return callerBytecodePosition; } + + private SourceLanguagePosition resolveSourceLanguagePosition() { + SourceLanguagePosition res = sourceLanguagePosition; + if (res == UnresolvedSourceLanguagePosition.INSTANCE) { + res = null; + if (arguments != null && method.hasReceiver() && arguments.length > 0 && arguments[0].isJavaConstant()) { + JavaConstant constantArgument = arguments[0].asJavaConstant(); + res = sourceLanguagePositionProvider.getPosition(constantArgument); + } + sourceLanguagePosition = res; + } + return res; + } + } + + private static final class UnresolvedSourceLanguagePosition implements SourceLanguagePosition { + static final SourceLanguagePosition INSTANCE = new UnresolvedSourceLanguagePosition(); + + @Override + public String toShortString() { + throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable."); + } + + @Override + public int getOffsetEnd() { + throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable."); + } + + @Override + public int getOffsetStart() { + throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable."); + } + + @Override + public int getLineNumber() { + throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable."); + } + + @Override + public URI getURI() { + throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable."); + } + + @Override + public String getLanguage() { + throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable."); + } } protected class PENonAppendGraphBuilderContext implements GraphBuilderContext { @@ -237,6 +282,21 @@ this.invoke = invoke; } + /** + * {@link Fold} and {@link NodeIntrinsic} can be deferred during parsing/decoding. Only by + * the end of {@linkplain SnippetTemplate#instantiate Snippet instantiation} do they need to + * have been processed. + * + * This is how SVM handles snippets. They are parsed with plugins disabled and then encoded + * and stored in the image. When the snippet is needed at runtime the graph is decoded and + * the plugins are run during the decoding process. If they aren't handled at this point + * then they will never be handled. + */ + @Override + public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) { + return plugin.getSource().equals(Fold.class) || plugin.getSource().equals(Node.NodeIntrinsic.class); + } + @Override public BailoutException bailout(String string) { BailoutException bailout = new PermanentBailoutException(string); @@ -1056,7 +1116,7 @@ ValueNode array = loadIndexedNode.array(); ValueNode index = loadIndexedNode.index(); for (NodePlugin nodePlugin : nodePlugins) { - if (nodePlugin.handleLoadIndexed(graphBuilderContext, array, index, loadIndexedNode.elementKind())) { + if (nodePlugin.handleLoadIndexed(graphBuilderContext, array, index, loadIndexedNode.getBoundsCheck(), loadIndexedNode.elementKind())) { replacedNode = graphBuilderContext.pushedNode; break; } @@ -1068,7 +1128,7 @@ ValueNode index = storeIndexedNode.index(); ValueNode value = storeIndexedNode.value(); for (NodePlugin nodePlugin : nodePlugins) { - if (nodePlugin.handleStoreIndexed(graphBuilderContext, array, index, storeIndexedNode.elementKind(), value)) { + if (nodePlugin.handleStoreIndexed(graphBuilderContext, array, index, storeIndexedNode.getBoundsCheck(), storeIndexedNode.getStoreCheck(), storeIndexedNode.elementKind(), value)) { replacedNode = graphBuilderContext.pushedNode; break; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu May 31 13:39:26 2018 -0700 @@ -51,6 +51,7 @@ import jdk.internal.vm.compiler.collections.EconomicSet; import jdk.internal.vm.compiler.collections.Equivalence; import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; +import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; @@ -70,6 +71,7 @@ import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Graph.Mark; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.Position; @@ -103,6 +105,7 @@ import org.graalvm.compiler.nodes.ValueNodeUtil; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.nodes.memory.MemoryAccess; import org.graalvm.compiler.nodes.memory.MemoryAnchorNode; @@ -510,7 +513,7 @@ } @Override - public ValueNode length() { + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { return ConstantNode.forInt(varargs.length); } } @@ -955,6 +958,8 @@ merge.setNext(this.returnNode); } + assert verifyIntrinsicsProcessed(snippetCopy); + this.sideEffectNodes = curSideEffectNodes; this.deoptNodes = curDeoptNodes; this.placeholderStampedNodes = curPlaceholderStampedNodes; @@ -977,6 +982,16 @@ } } + private static boolean verifyIntrinsicsProcessed(StructuredGraph snippetCopy) { + for (MethodCallTargetNode target : snippetCopy.getNodes(MethodCallTargetNode.TYPE)) { + ResolvedJavaMethod targetMethod = target.targetMethod(); + if (targetMethod != null) { + assert targetMethod.getAnnotation(Fold.class) == null && targetMethod.getAnnotation(NodeIntrinsic.class) == null : "plugin should have been processed"; + } + } + return true; + } + public static void explodeLoops(final StructuredGraph snippetCopy, PhaseContext phaseContext) { // Do any required loop explosion boolean exploded = false; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu May 31 13:39:26 2018 -0700 @@ -37,8 +37,6 @@ import java.lang.reflect.Field; import java.util.Arrays; -import jdk.vm.ci.code.BytecodePosition; -import jdk.vm.ci.meta.SpeculationLog; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; @@ -63,6 +61,7 @@ import org.graalvm.compiler.nodes.calc.AbsNode; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; +import org.graalvm.compiler.nodes.calc.FloatEqualsNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; import org.graalvm.compiler.nodes.calc.NarrowNode; import org.graalvm.compiler.nodes.calc.ReinterpretNode; @@ -97,6 +96,7 @@ import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; +import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode; @@ -107,6 +107,7 @@ import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode; import jdk.internal.vm.compiler.word.LocationIdentity; +import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; @@ -115,6 +116,7 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.SpeculationLog; import sun.misc.Unsafe; /** @@ -210,6 +212,76 @@ r.registerMethodSubstitution(ArraySubstitutions.class, "getLength", Object.class); } + private abstract static class UnsafeCompareAndUpdatePluginsRegistrar { + public void register(Registration r, String casPrefix, JavaKind[] compareAndSwapTypes) { + for (JavaKind kind : compareAndSwapTypes) { + Class javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass(); + r.register5(casPrefix + kind.name(), Receiver.class, Object.class, long.class, javaClass, javaClass, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode expected, ValueNode x) { + // Emits a null-check for the otherwise unused receiver + unsafe.get(); + b.addPush(returnKind(kind), createNode(object, offset, expected, x, kind, LocationIdentity.any())); + b.getGraph().markUnsafeAccess(); + return true; + } + }); + } + } + + public abstract ValueNode createNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind kind, LocationIdentity identity); + + public abstract JavaKind returnKind(JavaKind accessKind); + } + + private static class UnsafeCompareAndSwapPluginsRegistrar extends UnsafeCompareAndUpdatePluginsRegistrar { + @Override + public ValueNode createNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind kind, LocationIdentity identity) { + return new UnsafeCompareAndSwapNode(object, offset, expected, newValue, kind, LocationIdentity.any()); + } + + @Override + public JavaKind returnKind(JavaKind accessKind) { + return JavaKind.Boolean.getStackKind(); + } + } + + private static UnsafeCompareAndSwapPluginsRegistrar unsafeCompareAndSwapPluginsRegistrar = new UnsafeCompareAndSwapPluginsRegistrar(); + + private static class UnsafeCompareAndExchangePluginsRegistrar extends UnsafeCompareAndUpdatePluginsRegistrar { + @Override + public ValueNode createNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind kind, LocationIdentity identity) { + return new UnsafeCompareAndExchangeNode(object, offset, expected, newValue, kind, LocationIdentity.any()); + } + + @Override + public JavaKind returnKind(JavaKind accessKind) { + if (accessKind.isNumericInteger()) { + return accessKind.getStackKind(); + } else { + return accessKind; + } + } + } + + private static UnsafeCompareAndExchangePluginsRegistrar unsafeCompareAndExchangePluginsRegistrar = new UnsafeCompareAndExchangePluginsRegistrar(); + + public static void registerPlatformSpecificUnsafePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, JavaKind[] supportedCasKinds) { + Registration r; + if (Java8OrEarlier) { + r = new Registration(plugins, Unsafe.class); + } else { + r = new Registration(plugins, "jdk.internal.misc.Unsafe", bytecodeProvider); + } + + if (Java8OrEarlier) { + unsafeCompareAndSwapPluginsRegistrar.register(r, "compareAndSwap", new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}); + } else { + unsafeCompareAndSwapPluginsRegistrar.register(r, "compareAndSet", supportedCasKinds); + unsafeCompareAndExchangePluginsRegistrar.register(r, "compareAndExchange", supportedCasKinds); + } + } + private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { Registration r; if (Java8OrEarlier) { @@ -250,26 +322,6 @@ r.register2("getAddress", Receiver.class, long.class, new UnsafeGetPlugin(JavaKind.Long, false)); r.register3("putAddress", Receiver.class, long.class, long.class, new UnsafePutPlugin(JavaKind.Long, false)); - for (JavaKind kind : new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}) { - Class javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass(); - String casName; - if (Java8OrEarlier) { - casName = "compareAndSwap"; - } else { - casName = "compareAndSet"; - } - r.register5(casName + kind.name(), Receiver.class, Object.class, long.class, javaClass, javaClass, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode expected, ValueNode x) { - // Emits a null-check for the otherwise unused receiver - unsafe.get(); - b.addPush(JavaKind.Int, new UnsafeCompareAndSwapNode(object, offset, expected, x, kind, LocationIdentity.any())); - b.getGraph().markUnsafeAccess(); - return true; - } - }); - } - r.register2("allocateInstance", Receiver.class, Class.class, new InvocationPlugin() { @Override @@ -301,14 +353,14 @@ r.register2("divideUnsigned", type, type, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode dividend, ValueNode divisor) { - b.push(kind, b.append(UnsignedDivNode.create(dividend, divisor, NodeView.DEFAULT))); + b.push(kind, b.append(UnsignedDivNode.create(dividend, divisor, null, NodeView.DEFAULT))); return true; } }); r.register2("remainderUnsigned", type, type, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode dividend, ValueNode divisor) { - b.push(kind, b.append(UnsignedRemNode.create(dividend, divisor, NodeView.DEFAULT))); + b.push(kind, b.append(UnsignedRemNode.create(dividend, divisor, null, NodeView.DEFAULT))); return true; } }); @@ -353,6 +405,16 @@ return true; } }); + r.register1("floatToIntBits", float.class, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { + LogicNode notNan = b.append(FloatEqualsNode.create(value, value, NodeView.DEFAULT)); + ValueNode raw = b.append(ReinterpretNode.create(JavaKind.Int, value, NodeView.DEFAULT)); + ValueNode result = b.append(ConditionalNode.create(notNan, raw, ConstantNode.forInt(0x7fc00000), NodeView.DEFAULT)); + b.push(JavaKind.Int, result); + return true; + } + }); r.register1("intBitsToFloat", int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { @@ -371,6 +433,16 @@ return true; } }); + r.register1("doubleToLongBits", double.class, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { + LogicNode notNan = b.append(FloatEqualsNode.create(value, value, NodeView.DEFAULT)); + ValueNode raw = b.append(ReinterpretNode.create(JavaKind.Long, value, NodeView.DEFAULT)); + ValueNode result = b.append(ConditionalNode.create(notNan, raw, ConstantNode.forLong(0x7ff8000000000000L), NodeView.DEFAULT)); + b.push(JavaKind.Long, result); + return true; + } + }); r.register1("longBitsToDouble", long.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { @@ -906,6 +978,11 @@ b.add(new BlackholeNode(value)); return true; } + + @Override + public boolean isDecorator() { + return true; + } }; String[] names = {"org.openjdk.jmh.infra.Blackhole", "org.openjdk.jmh.logic.BlackHole"}; for (String name : names) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/D --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/D Wed May 30 11:36:46 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java -index 88403c3..728297d 100644 ---- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java -+++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java -@@ -138,7 +138,11 @@ public final class ClassfileBytecodeProvider implements BytecodeProvider { - return classfile; - } - -- synchronized Class resolveToClass(String descriptor) { -+ Class resolveToClass(String descriptor) { -+ return resolveToClass(descriptor, false); -+ } -+ -+ synchronized Class resolveToClass(String descriptor, boolean initialize) { - Class c = classes.get(descriptor); - if (c == null) { - if (descriptor.length() == 1) { -@@ -155,7 +159,7 @@ public final class ClassfileBytecodeProvider implements BytecodeProvider { - name = descriptor.replace('/', '.'); - } - try { -- c = Class.forName(name, true, loader); -+ c = Class.forName(name, initialize, loader); - classes.put(descriptor, c); - } catch (ClassNotFoundException e) { - throw new NoClassDefFoundError(descriptor); -diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java -index 087f78b..bde2dd4 100644 ---- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java -+++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java -@@ -70,8 +70,9 @@ abstract class ClassfileConstant { - * @param cp - * @param index - * @param opcode -+ * @param initialize - */ -- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) { -+ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) { - } - - @Override -@@ -90,15 +91,19 @@ abstract class ClassfileConstant { - } - - @Override -- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) { -- resolve(cp); -+ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) { -+ resolve(cp, initialize); - } - - public ResolvedJavaType resolve(ClassfileConstantPool cp) throws GraalError { -+ return resolve(cp, false /* initialize */); -+ } -+ -+ public ResolvedJavaType resolve(ClassfileConstantPool cp, boolean initialize) throws GraalError { - if (type == null) { - String typeDescriptor = cp.get(Utf8.class, nameIndex).value; - ClassfileBytecodeProvider context = cp.context; -- type = context.metaAccess.lookupJavaType(context.resolveToClass(typeDescriptor)); -+ type = context.metaAccess.lookupJavaType(context.resolveToClass(typeDescriptor, initialize)); - } - return type; - } -@@ -116,8 +121,8 @@ abstract class ClassfileConstant { - } - - @Override -- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) { -- cp.get(ClassRef.class, classIndex).loadReferencedType(cp, classIndex, opcode); -+ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) { -+ cp.get(ClassRef.class, classIndex).loadReferencedType(cp, classIndex, opcode, initialize); - } - } - -@@ -269,7 +274,7 @@ abstract class ClassfileConstant { - } - - @Override -- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) { -+ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) { - throw new GraalError("Resolution of " + name + " constant pool entries not supported by " + ClassfileBytecodeProvider.class.getSimpleName()); - } - } -diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java -index 218df10..a54779b 100644 ---- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java -+++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java -@@ -133,11 +133,11 @@ class ClassfileConstantPool implements ConstantPool { - } - - @Override -- public void loadReferencedType(int index, int opcode) { -+ public void loadReferencedType(int index, int opcode, boolean initialize) { - if (opcode == Bytecodes.INVOKEDYNAMIC) { - throw new GraalError("INVOKEDYNAMIC not supported by " + ClassfileBytecodeProvider.class.getSimpleName()); - } -- entries[index].loadReferencedType(this, index, opcode); -+ entries[index].loadReferencedType(this, index, opcode, initialize); - } - - @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu May 31 13:39:26 2018 -0700 @@ -234,7 +234,8 @@ return; } for (int i = 0; i < len; i++) { - LoadIndexedNode load = new LoadIndexedNode(graph().getAssumptions(), srcAlias, ConstantNode.forInt(i + srcPosInt, graph()), destComponentType.getJavaKind()); + LoadIndexedNode load = new LoadIndexedNode(graph().getAssumptions(), srcAlias, ConstantNode.forInt(i + srcPosInt, graph()), null, destComponentType.getJavaKind()); + load.setNodeSourcePosition(getNodeSourcePosition()); tool.addNode(load); tool.setVirtualEntry(destVirtual, destPosInt + i, load); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Thu May 31 13:39:26 2018 -0700 @@ -139,7 +139,7 @@ } @Override - public ValueNode length() { - return GraphUtil.arrayLength(getObject()); + public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) { + return GraphUtil.arrayLength(getObject(), mode); } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java Thu May 31 13:39:26 2018 -0700 @@ -333,7 +333,7 @@ FixedGuardNode fixedGuard = adder.add(new FixedGuardNode(inst, reason, action, speculation, false)); guard = fixedGuard; } else { - GuardNode newGuard = adder.add(new GuardNode(inst, guardAnchor, reason, action, false, speculation)); + GuardNode newGuard = adder.add(new GuardNode(inst, guardAnchor, reason, action, false, speculation, null)); adder.add(new ValueAnchorNode(newGuard)); guard = newGuard; } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,34 +22,27 @@ */ package org.graalvm.compiler.serviceprovider.processor; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.FilerException; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic.Kind; -import javax.tools.FileObject; -import javax.tools.StandardLocation; -import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.compiler.processor.AbstractProcessor; /** - * Processes classes annotated with {@link ServiceProvider}. For a service defined by {@code S} and + * Processes classes annotated with {@code ServiceProvider}. For a service defined by {@code S} and * a class {@code P} implementing the service, this processor generates the file * {@code META-INF/providers/P} whose contents are a single line containing the fully qualified name * of {@code S}. @@ -57,6 +50,7 @@ @SupportedAnnotationTypes("org.graalvm.compiler.serviceprovider.ServiceProvider") public class ServiceProviderProcessor extends AbstractProcessor { + private static final String SERVICE_PROVIDER_CLASS_NAME = "org.graalvm.compiler.serviceprovider.ServiceProvider"; private final Set processed = new HashSet<>(); private final Map serviceProviders = new HashMap<>(); @@ -81,90 +75,59 @@ } processed.add(serviceProvider); - ServiceProvider annotation = serviceProvider.getAnnotation(ServiceProvider.class); + AnnotationMirror annotation = getAnnotation(serviceProvider, getType(SERVICE_PROVIDER_CLASS_NAME)); if (annotation != null) { - try { - annotation.value(); - } catch (MirroredTypeException ex) { - TypeMirror service = ex.getTypeMirror(); - if (verifyAnnotation(service, serviceProvider)) { - if (serviceProvider.getNestingKind().isNested()) { - /* - * This is a simplifying constraint that means we don't have to process the - * qualified name to insert '$' characters at the relevant positions. - */ - String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); - } else { - /* - * Since the definition of the service class is not necessarily modifiable, - * we need to support a non-top-level service class and ensure its name is - * properly expressed with '$' separating nesting levels instead of '.'. - */ - TypeElement serviceElement = (TypeElement) processingEnv.getTypeUtils().asElement(service); - String serviceName = serviceElement.getSimpleName().toString(); - Element enclosing = serviceElement.getEnclosingElement(); - while (enclosing != null) { - final ElementKind kind = enclosing.getKind(); - if (kind == ElementKind.PACKAGE) { - serviceName = ((PackageElement) enclosing).getQualifiedName().toString() + "." + serviceName; - break; - } else if (kind == ElementKind.CLASS || kind == ElementKind.INTERFACE) { - serviceName = ((TypeElement) enclosing).getSimpleName().toString() + "$" + serviceName; - enclosing = enclosing.getEnclosingElement(); - } else { - String msg = String.format("Cannot generate provider descriptor for service class %s as it is not nested in a package, class or interface", - serviceElement.getQualifiedName()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); - return; - } + TypeMirror service = getAnnotationValue(annotation, "value", TypeMirror.class); + if (verifyAnnotation(service, serviceProvider)) { + if (serviceProvider.getNestingKind().isNested()) { + /* + * This is a simplifying constraint that means we don't have to process the + * qualified name to insert '$' characters at the relevant positions. + */ + String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName()); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); + } else { + /* + * Since the definition of the service class is not necessarily modifiable, we + * need to support a non-top-level service class and ensure its name is properly + * expressed with '$' separating nesting levels instead of '.'. + */ + TypeElement serviceElement = (TypeElement) processingEnv.getTypeUtils().asElement(service); + String serviceName = serviceElement.getSimpleName().toString(); + Element enclosing = serviceElement.getEnclosingElement(); + while (enclosing != null) { + final ElementKind kind = enclosing.getKind(); + if (kind == ElementKind.PACKAGE) { + serviceName = ((PackageElement) enclosing).getQualifiedName().toString() + "." + serviceName; + break; + } else if (kind == ElementKind.CLASS || kind == ElementKind.INTERFACE) { + serviceName = ((TypeElement) enclosing).getSimpleName().toString() + "$" + serviceName; + enclosing = enclosing.getEnclosingElement(); + } else { + String msg = String.format("Cannot generate provider descriptor for service class %s as it is not nested in a package, class or interface", + serviceElement.getQualifiedName()); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); + return; } - serviceProviders.put(serviceProvider, serviceName); } + serviceProviders.put(serviceProvider, serviceName); } } } } - private void writeProviderFile(TypeElement serviceProvider, String interfaceName) { - String filename = "META-INF/providers/" + serviceProvider.getQualifiedName(); - try { - FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, serviceProvider); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); - writer.println(interfaceName); - writer.close(); - } catch (IOException e) { - processingEnv.getMessager().printMessage(isBug367599(e) ? Kind.NOTE : Kind.ERROR, e.getMessage(), serviceProvider); - } - } - - /** - * Determines if a given exception is (most likely) caused by - * Bug 367599. - */ - private static boolean isBug367599(Throwable t) { - if (t instanceof FilerException) { - for (StackTraceElement ste : t.getStackTrace()) { - if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) { - // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599 - return true; - } - } - } - return t.getCause() != null && isBug367599(t.getCause()); - } - @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { for (Entry e : serviceProviders.entrySet()) { - writeProviderFile(e.getKey(), e.getValue()); + createProviderFile(e.getKey().getQualifiedName().toString(), e.getValue(), e.getKey()); } serviceProviders.clear(); return true; } - for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) { + TypeElement serviceProviderTypeElement = getTypeElement(SERVICE_PROVIDER_CLASS_NAME); + for (Element element : roundEnv.getElementsAnnotatedWith(serviceProviderTypeElement)) { assert element.getKind().isClass(); processElement((TypeElement) element); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java Thu May 31 13:39:26 2018 -0700 @@ -26,8 +26,10 @@ import java.util.Arrays; import java.util.List; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -183,6 +185,7 @@ * This transitively also materializes all other virtual objects that are reachable from the * entries. */ + @SuppressWarnings("try") public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) { PartialEscapeClosure.COUNTER_MATERIALIZATIONS.increment(fixed.getDebug()); List objects = new ArrayList<>(2); @@ -209,8 +212,10 @@ if (fixed.predecessor() instanceof CommitAllocationNode) { commit = (CommitAllocationNode) fixed.predecessor(); } else { - commit = graph.add(new CommitAllocationNode()); - graph.addBeforeFixed(fixed, commit); + try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.placeholder(graph.method()))) { + commit = graph.add(new CommitAllocationNode()); + graph.addBeforeFixed(fixed, commit); + } } for (AllocatedObjectNode obj : objects) { graph.addWithoutUnique(obj); diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Thu May 31 13:39:26 2018 -0700 @@ -650,7 +650,9 @@ if (needsCaching) { return getValueObjectVirtualCached(phi, virtual); } else { - return virtual.duplicate(); + VirtualObjectNode duplicate = virtual.duplicate(); + duplicate.setNodeSourcePosition(virtual.getNodeSourcePosition()); + return duplicate; } } @@ -661,6 +663,7 @@ VirtualObjectNode result = valueObjectVirtuals.get(phi); if (result == null) { result = virtual.duplicate(); + result.setNodeSourcePosition(virtual.getNodeSourcePosition()); valueObjectVirtuals.put(phi, result); } return result; diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java Thu May 31 13:39:26 2018 -0700 @@ -88,6 +88,7 @@ */ public enum Opcode { NODE_CLASS, + NODE_CLASS_WITH_GUARD, COMPARISON, IS_NULL, IS_NON_NULL, @@ -248,69 +249,69 @@ } @Override - @Operation(node = SignedDivNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = SignedDivNode.class) public Word signedDivide(SignedWord val) { return signedDivide((Word) val); } @Override - @Operation(node = SignedDivNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = SignedDivNode.class) public Word signedDivide(int val) { return signedDivide(intParam(val)); } - @Operation(node = SignedDivNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = SignedDivNode.class) public Word signedDivide(Word val) { return box(unbox() / val.unbox()); } @Override - @Operation(node = UnsignedDivNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = UnsignedDivNode.class) public Word unsignedDivide(UnsignedWord val) { return unsignedDivide((Word) val); } @Override - @Operation(node = UnsignedDivNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = UnsignedDivNode.class) public Word unsignedDivide(int val) { return signedDivide(intParam(val)); } - @Operation(node = UnsignedDivNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = UnsignedDivNode.class) public Word unsignedDivide(Word val) { return box(Long.divideUnsigned(unbox(), val.unbox())); } @Override - @Operation(node = SignedRemNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = SignedRemNode.class) public Word signedRemainder(SignedWord val) { return signedRemainder((Word) val); } @Override - @Operation(node = SignedRemNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = SignedRemNode.class) public Word signedRemainder(int val) { return signedRemainder(intParam(val)); } - @Operation(node = SignedRemNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = SignedRemNode.class) public Word signedRemainder(Word val) { return box(unbox() % val.unbox()); } @Override - @Operation(node = UnsignedRemNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = UnsignedRemNode.class) public Word unsignedRemainder(UnsignedWord val) { return unsignedRemainder((Word) val); } @Override - @Operation(node = UnsignedRemNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = UnsignedRemNode.class) public Word unsignedRemainder(int val) { return signedRemainder(intParam(val)); } - @Operation(node = UnsignedRemNode.class) + @Operation(opcode = Opcode.NODE_CLASS_WITH_GUARD, node = UnsignedRemNode.class) public Word unsignedRemainder(Word val) { return box(Long.remainderUnsigned(unbox(), val.unbox())); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Thu May 31 13:39:26 2018 -0700 @@ -51,6 +51,7 @@ import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.JavaReadNode; import org.graalvm.compiler.nodes.extended.JavaWriteNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -160,7 +161,7 @@ } @Override - public boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind) { + public boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { ResolvedJavaType arrayType = StampTool.typeOrNull(array); /* * There are cases where the array does not have a known type yet, i.e., the type is null. @@ -168,14 +169,14 @@ */ if (arrayType != null && wordTypes.isWord(arrayType.getComponentType())) { assert elementKind == JavaKind.Object; - b.addPush(elementKind, createLoadIndexedNode(array, index)); + b.addPush(elementKind, createLoadIndexedNode(array, index, boundsCheck)); return true; } return false; } - protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) { - return new LoadIndexedNode(null, array, index, wordKind); + protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index, GuardingNode boundsCheck) { + return new LoadIndexedNode(null, array, index, boundsCheck, wordKind); } @Override @@ -201,14 +202,15 @@ } @Override - public boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind, ValueNode value) { + public boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind elementKind, ValueNode value) { ResolvedJavaType arrayType = StampTool.typeOrNull(array); if (arrayType != null && wordTypes.isWord(arrayType.getComponentType())) { assert elementKind == JavaKind.Object; if (value.getStackKind() != wordKind) { throw bailout(b, "Cannot store a non-word value into a word array: " + arrayType.toJavaName(true)); } - b.add(createStoreIndexedNode(array, index, value)); + GraalError.guarantee(storeCheck == null, "Word array stores are primitive stores and therefore do not require a store check"); + b.add(createStoreIndexedNode(array, index, boundsCheck, value)); return true; } if (elementKind == JavaKind.Object && value.getStackKind() == wordKind) { @@ -217,8 +219,8 @@ return false; } - protected StoreIndexedNode createStoreIndexedNode(ValueNode array, ValueNode index, ValueNode value) { - return new StoreIndexedNode(array, index, wordKind, value); + protected StoreIndexedNode createStoreIndexedNode(ValueNode array, ValueNode index, GuardingNode boundsCheck, ValueNode value) { + return new StoreIndexedNode(array, index, boundsCheck, null, wordKind, value); } @Override @@ -275,11 +277,12 @@ } switch (operation.opcode()) { case NODE_CLASS: + case NODE_CLASS_WITH_GUARD: assert args.length == 2; ValueNode left = args[0]; ValueNode right = operation.rightOperandIsInt() ? toUnsigned(b, args[1], JavaKind.Int) : fromSigned(b, args[1]); - b.addPush(returnKind, createBinaryNodeInstance(operation.node(), left, right)); + b.addPush(returnKind, createBinaryNodeInstance(operation.node(), left, right, operation.opcode() == Opcode.NODE_CLASS_WITH_GUARD)); break; case COMPARISON: @@ -399,10 +402,12 @@ * method is called for all {@link Word} operations which are annotated with @Operation(node = * ...) and encapsulates the reflective allocation of the node. */ - private static ValueNode createBinaryNodeInstance(Class nodeClass, ValueNode left, ValueNode right) { + private static ValueNode createBinaryNodeInstance(Class nodeClass, ValueNode left, ValueNode right, boolean withGuardingNode) { try { - Constructor cons = nodeClass.getDeclaredConstructor(ValueNode.class, ValueNode.class); - return (ValueNode) cons.newInstance(left, right); + Class[] parameterTypes = withGuardingNode ? new Class[]{ValueNode.class, ValueNode.class, GuardingNode.class} : new Class[]{ValueNode.class, ValueNode.class}; + Constructor cons = nodeClass.getDeclaredConstructor(parameterTypes); + Object[] initargs = withGuardingNode ? new Object[]{left, right, null} : new Object[]{left, right}; + return (ValueNode) cons.newInstance(initargs); } catch (Throwable ex) { throw new GraalError(ex).addContext(nodeClass.getName()); } diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java Thu May 31 13:39:26 2018 -0700 @@ -149,8 +149,8 @@ static GraphOutput buildOutput(WritableByteChannel channel) throws IOException { return GraphOutput.newBuilder(acmeGraphStructure()). - // use the latest version; currently 5.0 - protocolVersion(5, 0). + // use the latest version; currently 6.0 + protocolVersion(6, 0). build(channel); } // END: org.graalvm.graphio.GraphJavadocSnippets#buildOutput @@ -164,7 +164,7 @@ GraphTypes graphTypes = acmeTypes(); return GraphOutput.newBuilder(acmeGraphStructure()). - protocolVersion(5, 0). + protocolVersion(6, 0). blocks(graphBlocks). elements(graphElements). types(graphTypes). diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Thu May 31 13:39:26 2018 -0700 @@ -606,7 +606,7 @@ throw new IOException(ex); } if (uri == null) { - throw new IOException("No URI for " + loc); + continue; } String l = findLocationLanguage(loc); if (l == null) { diff -r d66751750b72 -r c10dbcaed048 src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java Thu May 31 13:39:26 2018 -0700 @@ -78,7 +78,11 @@ @Override protected NodeClass findClassForNode(Node obj) { - return structure.classForNode(obj); + NodeClass clazz = structure.classForNode(obj); + if (clazz != null && (findNodeClass(clazz) == null || findNode(clazz) != null)) { + throw new IllegalStateException("classForNode method shall return node class representation rather than node: " + clazz); + } + return clazz; } @Override diff -r d66751750b72 -r c10dbcaed048 src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java --- a/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,16 +49,55 @@ return quickAckSupported0(); } - native static private void setQuickAck0(int fd, boolean on) throws SocketException; + @Override + boolean keepAliveOptionsSupported() { + return keepAliveOptionsSupported0(); + } + + @Override + void setTcpkeepAliveProbes(int fd, final int value) throws SocketException { + setTcpkeepAliveProbes0(fd, value); + } + + @Override + void setTcpKeepAliveTime(int fd, final int value) throws SocketException { + setTcpKeepAliveTime0(fd, value); + } + + @Override + void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException { + setTcpKeepAliveIntvl0(fd, value); + } - native static private boolean getQuickAck0(int fd) throws SocketException; + @Override + int getTcpkeepAliveProbes(int fd) throws SocketException { + return getTcpkeepAliveProbes0(fd); + } + + @Override + int getTcpKeepAliveTime(int fd) throws SocketException { + return getTcpKeepAliveTime0(fd); + } - native static private boolean quickAckSupported0(); + @Override + int getTcpKeepAliveIntvl(int fd) throws SocketException { + return getTcpKeepAliveIntvl0(fd); + } + private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException; + private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException; + private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException; + private static native int getTcpkeepAliveProbes0(int fd) throws SocketException; + private static native int getTcpKeepAliveTime0(int fd) throws SocketException; + private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException; + private static native void setQuickAck0(int fd, boolean on) throws SocketException; + private static native boolean getQuickAck0(int fd) throws SocketException; + private static native boolean keepAliveOptionsSupported0(); + private static native boolean quickAckSupported0(); static { AccessController.doPrivileged((PrivilegedAction) () -> { System.loadLibrary("extnet"); return null; }); } -} +} \ No newline at end of file diff -r d66751750b72 -r c10dbcaed048 src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c --- a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include #include +#include #include "jni_util.h" /* @@ -97,3 +98,117 @@ close(s); return rv; } + +static jint socketOptionSupported(jint sockopt) { + jint one = 1; + jint rv, s; + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) { + return 0; + } + rv = setsockopt(s, SOL_TCP, sockopt, (void *) &one, sizeof (one)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = 0; + } else { + rv = 1; + } + close(s); + return rv; +} + +static void handleError(JNIEnv *env, jint rv, const char *errmsg) { + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + JNU_ThrowByNameWithLastError(env, "java/net/SocketException", errmsg); + } + } +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: keepAliveOptionsSupported0 + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_keepAliveOptionsSupported0 +(JNIEnv *env, jobject unused) { + return socketOptionSupported(TCP_KEEPIDLE) && socketOptionSupported(TCP_KEEPCNT) + && socketOptionSupported(TCP_KEEPINTVL); +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: setTcpkeepAliveProbes0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setTcpkeepAliveProbes0 +(JNIEnv *env, jobject unused, jint fd, jint optval) { + jint rv = setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &optval, sizeof (optval)); + handleError(env, rv, "set option TCP_KEEPCNT failed"); +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: setTcpKeepAliveTime0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setTcpKeepAliveTime0 +(JNIEnv *env, jobject unused, jint fd, jint optval) { + jint rv = setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof (optval)); + handleError(env, rv, "set option TCP_KEEPIDLE failed"); +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: setTcpKeepAliveIntvl0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setTcpKeepAliveIntvl0 +(JNIEnv *env, jobject unused, jint fd, jint optval) { + jint rv = setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof (optval)); + handleError(env, rv, "set option TCP_KEEPINTVL failed"); +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: getTcpkeepAliveProbes0 + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getTcpkeepAliveProbes0 +(JNIEnv *env, jobject unused, jint fd) { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, SOL_TCP, TCP_KEEPCNT, &optval, &sz); + handleError(env, rv, "get option TCP_KEEPCNT failed"); + return optval; +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: getTcpKeepAliveTime0 + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getTcpKeepAliveTime0 +(JNIEnv *env, jobject unused, jint fd) { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, &sz); + handleError(env, rv, "get option TCP_KEEPIDLE failed"); + return optval; +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: getTcpKeepAliveIntvl0 + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getTcpKeepAliveIntvl0 +(JNIEnv *env, jobject unused, jint fd) { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, &sz); + handleError(env, rv, "get option TCP_KEEPINTVL failed"); + return optval; +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.net; + +import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; + +class MacOSXSocketOptions extends PlatformSocketOptions { + + public MacOSXSocketOptions() { + } + + @Override + boolean keepAliveOptionsSupported() { + return keepAliveOptionsSupported0(); + } + + @Override + void setTcpkeepAliveProbes(int fd, final int value) throws SocketException { + setTcpkeepAliveProbes0(fd, value); + } + + @Override + void setTcpKeepAliveTime(int fd, final int value) throws SocketException { + setTcpKeepAliveTime0(fd, value); + } + + @Override + void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException { + setTcpKeepAliveIntvl0(fd, value); + } + + @Override + int getTcpkeepAliveProbes(int fd) throws SocketException { + return getTcpkeepAliveProbes0(fd); + } + + @Override + int getTcpKeepAliveTime(int fd) throws SocketException { + return getTcpKeepAliveTime0(fd); + } + + @Override + int getTcpKeepAliveIntvl(int fd) throws SocketException { + return getTcpKeepAliveIntvl0(fd); + } + + private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException; + private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException; + private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException; + private static native int getTcpkeepAliveProbes0(int fd) throws SocketException; + private static native int getTcpKeepAliveTime0(int fd) throws SocketException; + private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException; + private static native boolean keepAliveOptionsSupported0(); + static { + AccessController.doPrivileged((PrivilegedAction) () -> { + System.loadLibrary("extnet"); + return null; + }); + } +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include +#include +#include +#include + +#include +#include +#include +#include "jni_util.h" + +static jint socketOptionSupported(jint sockopt) { + jint one = 1; + jint rv, s; + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) { + return 0; + } + rv = setsockopt(s, IPPROTO_TCP, sockopt, (void *) &one, sizeof (one)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = 0; + } else { + rv = 1; + } + close(s); + return rv; +} + +static void handleError(JNIEnv *env, jint rv, const char *errmsg) { + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + JNU_ThrowByNameWithLastError(env, "java/net/SocketException", errmsg); + } + } +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: keepAliveOptionsSupported0 + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_jdk_net_MacOSXSocketOptions_keepAliveOptionsSupported0 +(JNIEnv *env, jobject unused) { + return socketOptionSupported(TCP_KEEPALIVE) && socketOptionSupported(TCP_KEEPCNT) + && socketOptionSupported(TCP_KEEPINTVL); +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: setTcpkeepAliveProbes0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setTcpkeepAliveProbes0 +(JNIEnv *env, jobject unused, jint fd, jint optval) { + jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof (optval)); + handleError(env, rv, "set option TCP_KEEPCNT failed"); +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: setTcpKeepAliveTime0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setTcpKeepAliveTime0 +(JNIEnv *env, jobject unused, jint fd, jint optval) { + jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &optval, sizeof (optval)); + handleError(env, rv, "set option TCP_KEEPALIVE failed");// mac TCP_KEEPIDLE ->TCP_KEEPALIVE +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: setTcpKeepAliveIntvl0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setTcpKeepAliveIntvl0 +(JNIEnv *env, jobject unused, jint fd, jint optval) { + jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof (optval)); + handleError(env, rv, "set option TCP_KEEPINTVL failed"); +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: getTcpkeepAliveProbes0 + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpkeepAliveProbes0 +(JNIEnv *env, jobject unused, jint fd) { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, &sz); + handleError(env, rv, "get option TCP_KEEPCNT failed"); + return optval; +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: getTcpKeepAliveTime0 + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpKeepAliveTime0 +(JNIEnv *env, jobject unused, jint fd) { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &optval, &sz); + handleError(env, rv, "get option TCP_KEEPALIVE failed");// mac TCP_KEEPIDLE ->TCP_KEEPALIVE + return optval; +} + +/* + * Class: jdk_net_MacOSXSocketOptions + * Method: getTcpKeepAliveIntvl0 + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpKeepAliveIntvl0 +(JNIEnv *env, jobject unused, jint fd) { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, &sz); + handleError(env, rv, "get option TCP_KEEPINTVL failed"); + return optval; +} diff -r d66751750b72 -r c10dbcaed048 src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java --- a/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collections; +import java.util.HashSet; import java.util.Set; import jdk.internal.misc.JavaIOFileDescriptorAccess; import jdk.internal.misc.SharedSecrets; @@ -92,6 +93,74 @@ public static final SocketOption TCP_QUICKACK = new ExtSocketOption("TCP_QUICKACK", Boolean.class); + /** + * Keep-Alive idle time. + * + *

+ * The value of this socket option is an {@code Integer} that is the number + * of seconds of idle time before keep-alive initiates a probe. The socket + * option is specific to stream-oriented sockets using the TCP/IP protocol. + * The exact semantics of this socket option are system dependent. + * + *

+ * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE + * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been + * idle for some amount of time. The default value for this idle period is + * system dependent, but is typically 2 hours. The {@code TCP_KEEPIDLE} + * option can be used to affect this value for a given socket. + * + * @since 11 + */ + public static final SocketOption TCP_KEEPIDLE + = new ExtSocketOption("TCP_KEEPIDLE", Integer.class); + + /** + * Keep-Alive retransmission interval time. + * + *

+ * The value of this socket option is an {@code Integer} that is the number + * of seconds to wait before retransmitting a keep-alive probe. The socket + * option is specific to stream-oriented sockets using the TCP/IP protocol. + * The exact semantics of this socket option are system dependent. + * + *

+ * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE + * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been + * idle for some amount of time. If the remote system does not respond to a + * keep-alive probe, TCP retransmits the probe after some amount of time. + * The default value for this retransmission interval is system dependent, + * but is typically 75 seconds. The {@code TCP_KEEPINTERVAL} option can be + * used to affect this value for a given socket. + * + * @since 11 + */ + public static final SocketOption TCP_KEEPINTERVAL + = new ExtSocketOption("TCP_KEEPINTERVAL", Integer.class); + + /** + * Keep-Alive retransmission maximum limit. + * + *

+ * The value of this socket option is an {@code Integer} that is the maximum + * number of keep-alive probes to be sent. The socket option is specific to + * stream-oriented sockets using the TCP/IP protocol. The exact semantics of + * this socket option are system dependent. + * + *

+ * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE + * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been + * idle for some amount of time. If the remote system does not respond to a + * keep-alive probe, TCP retransmits the probe a certain number of times + * before a connection is considered to be broken. The default value for + * this keep-alive probe retransmit limit is system dependent, but is + * typically 8. The {@code TCP_KEEPCOUNT} option can be used to affect this + * value for a given socket. + * + * @since 11 + */ + public static final SocketOption TCP_KEEPCOUNT + = new ExtSocketOption("TCP_KEEPCOUNT", Integer.class); + private static final PlatformSocketOptions platformSocketOptions = PlatformSocketOptions.get(); @@ -99,21 +168,22 @@ platformSocketOptions.flowSupported(); private static final boolean quickAckSupported = platformSocketOptions.quickAckSupported(); - + private static final boolean keepAliveOptSupported = + platformSocketOptions.keepAliveOptionsSupported(); private static final Set> extendedOptions = options(); static Set> options() { + Set> options = new HashSet<>(); if (flowSupported) { - if (quickAckSupported) { - return Set.of(SO_FLOW_SLA, TCP_QUICKACK); - } else { - return Set.of(SO_FLOW_SLA); - } - } else if (quickAckSupported) { - return Set.of(TCP_QUICKACK); - } else { - return Collections.>emptySet(); + options.add(SO_FLOW_SLA); + } + if (quickAckSupported) { + options.add(TCP_QUICKACK); } + if (keepAliveOptSupported) { + options.addAll(Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL)); + } + return Collections.unmodifiableSet(options); } static { @@ -140,6 +210,12 @@ setFlowOption(fd, flow); } else if (option == TCP_QUICKACK) { setQuickAckOption(fd, (boolean) value); + } else if (option == TCP_KEEPCOUNT) { + setTcpkeepAliveProbes(fd, (Integer) value); + } else if (option == TCP_KEEPIDLE) { + setTcpKeepAliveTime(fd, (Integer) value); + } else if (option == TCP_KEEPINTERVAL) { + setTcpKeepAliveIntvl(fd, (Integer) value); } else { throw new InternalError("Unexpected option " + option); } @@ -164,6 +240,12 @@ return flow; } else if (option == TCP_QUICKACK) { return getQuickAckOption(fd); + } else if (option == TCP_KEEPCOUNT) { + return getTcpkeepAliveProbes(fd); + } else if (option == TCP_KEEPIDLE) { + return getTcpKeepAliveTime(fd); + } else if (option == TCP_KEEPINTERVAL) { + return getTcpKeepAliveIntvl(fd); } else { throw new InternalError("Unexpected option " + option); } @@ -208,6 +290,33 @@ return platformSocketOptions.getQuickAck(fdAccess.get(fd)); } + private static void setTcpkeepAliveProbes(FileDescriptor fd, int value) + throws SocketException { + platformSocketOptions.setTcpkeepAliveProbes(fdAccess.get(fd), value); + } + + private static void setTcpKeepAliveTime(FileDescriptor fd, int value) + throws SocketException { + platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value); + } + + private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value) + throws SocketException { + platformSocketOptions.setTcpKeepAliveIntvl(fdAccess.get(fd), value); + } + + private static int getTcpkeepAliveProbes(FileDescriptor fd) throws SocketException { + return platformSocketOptions.getTcpkeepAliveProbes(fdAccess.get(fd)); + } + + private static int getTcpKeepAliveTime(FileDescriptor fd) throws SocketException { + return platformSocketOptions.getTcpKeepAliveTime(fdAccess.get(fd)); + } + + private static int getTcpKeepAliveIntvl(FileDescriptor fd) throws SocketException { + return platformSocketOptions.getTcpKeepAliveIntvl(fdAccess.get(fd)); + } + static class PlatformSocketOptions { protected PlatformSocketOptions() {} @@ -234,6 +343,8 @@ return newInstance("jdk.net.SolarisSocketOptions"); } else if ("Linux".equals(osname)) { return newInstance("jdk.net.LinuxSocketOptions"); + } else if (osname.startsWith("Mac")) { + return newInstance("jdk.net.MacOSXSocketOptions"); } else { return new PlatformSocketOptions(); } @@ -270,5 +381,33 @@ boolean quickAckSupported() { return false; } + + boolean keepAliveOptionsSupported() { + return false; + } + + void setTcpkeepAliveProbes(int fd, final int value) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option"); + } + + void setTcpKeepAliveTime(int fd, final int value) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option"); + } + + void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option"); + } + + int getTcpkeepAliveProbes(int fd) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option"); + } + + int getTcpKeepAliveTime(int fd) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option"); + } + + int getTcpKeepAliveIntvl(int fd) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option"); + } } } diff -r d66751750b72 -r c10dbcaed048 src/jdk.net/share/classes/jdk/net/Sockets.java --- a/src/jdk.net/share/classes/jdk/net/Sockets.java Wed May 30 11:36:46 2018 -0700 +++ b/src/jdk.net/share/classes/jdk/net/Sockets.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -282,6 +282,11 @@ if (QuickAck.available) { set.add(ExtendedSocketOptions.TCP_QUICKACK); } + if (KeepAliveOptions.AVAILABLE) { + set.addAll(Set.of(ExtendedSocketOptions.TCP_KEEPCOUNT, + ExtendedSocketOptions.TCP_KEEPIDLE, + ExtendedSocketOptions.TCP_KEEPINTERVAL)); + } set = Collections.unmodifiableSet(set); options.put(Socket.class, set); @@ -296,6 +301,11 @@ if (QuickAck.available) { set.add(ExtendedSocketOptions.TCP_QUICKACK); } + if (KeepAliveOptions.AVAILABLE) { + set.addAll(Set.of(ExtendedSocketOptions.TCP_KEEPCOUNT, + ExtendedSocketOptions.TCP_KEEPIDLE, + ExtendedSocketOptions.TCP_KEEPINTERVAL)); + } set.add(StandardSocketOptions.IP_TOS); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); @@ -350,4 +360,19 @@ available = s.contains(ExtendedSocketOptions.TCP_QUICKACK); } } + + /** + * Tells whether TCP_KEEPALIVE options are supported. + */ + static class KeepAliveOptions { + + static final boolean AVAILABLE; + + static { + Set> s = new Socket().supportedOptions(); + AVAILABLE = s.containsAll(Set.of(ExtendedSocketOptions.TCP_KEEPCOUNT, + ExtendedSocketOptions.TCP_KEEPIDLE, + ExtendedSocketOptions.TCP_KEEPINTERVAL)); + } + } } diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/ProblemList.txt --- a/test/hotspot/jtreg/ProblemList.txt Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/ProblemList.txt Thu May 31 13:39:26 2018 -0700 @@ -172,4 +172,6 @@ vmTestbase/heapdump/JMapHeapCore/TestDescription.java 8023376,8001227,8051445 generic-all vmTestbase/heapdump/JMapMetaspaceCore/TestDescription.java 8023376,8001227,8051445 generic-all +vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all + ############################################################################# diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/TEST.groups --- a/test/hotspot/jtreg/TEST.groups Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/TEST.groups Thu May 31 13:39:26 2018 -0700 @@ -1750,6 +1750,122 @@ vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001/TestDescription.java \ vmTestbase/nsk/jvmti/unit/GetConstantPool/getcpool001/TestDescription.java +# JDWP tests +vmTestbase_nsk_jdwp = \ + vmTestbase/nsk/jdwp + +vmTestbase_nsk_jdwp_quick = \ + vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java \ + vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java \ + vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java \ + vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java \ + vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java \ + vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java \ + vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java \ + vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java \ + vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java \ + vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java \ + vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java \ + vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java \ + vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java \ + vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java \ + vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java \ + vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java \ + vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java \ + vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java \ + vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java \ + vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java \ + vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java \ + vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java \ + vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java \ + vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java \ + vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java \ + vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java \ + vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java \ + vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java \ + vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java \ + vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java \ + vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java \ + vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java \ + vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java \ + vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java \ + vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java \ + vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java + vmTestbase_nsk_stress = \ vmTestbase/nsk/stress @@ -1870,6 +1986,10 @@ vmTestbase/heapdump/JMapHeapCore/TestDescription.java \ vmTestbase/heapdump/JMapMetaspace/TestDescription.java +# Tests for attach-on-demand implementation +vmTestbase_nsk_aod = \ + vmTestbase/nsk/aod + # JDB tests vmTestbase_nsk_jdb = \ vmTestbase/nsk/jdb diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoadClass/TestResize.java --- a/test/hotspot/jtreg/runtime/LoadClass/TestResize.java Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/runtime/LoadClass/TestResize.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ */ import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -66,42 +67,61 @@ } static void analyzeOutputOn(ProcessBuilder pb) throws Exception { - pb.redirectErrorStream(true); - Process process = pb.start(); - BufferedReader rd = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line = rd.readLine(); - while (line != null) { - if (line.startsWith("Java dictionary (")) { - // ex. "Java dictionary (table_size=107, classes=6)" - // ex. "Java dictionary (table_size=20201, classes=50002)" + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + String output = analyzer.getStdout(); + analyzer.shouldHaveExitValue(0); + + boolean resized = false; + + // Split string into lines using platform independent end of line marker. + String[] lines = output.split("\\R"); + for (String line : lines) { + if (!resized) { + // ex. [0.563s][info][safepoint,cleanup] resizing system dictionaries, 0.0000002 secs + if (line.contains("resizing system dictionaries")) { + resized = true; + } + } else if (resized && line.startsWith("Java dictionary (")) { + // ex. Java dictionary (table_size=10103, classes=5002) Scanner scanner = new Scanner(line); - scanner.next(); - scanner.next(); - int table_size = getInt(scanner.next()); - int classes = getInt(scanner.next()); + scanner.next(); // skip "Java" + scanner.next(); // skip "dictionary" + int table_size = getInt(scanner.next()); // process "(table_size=40423" + int classes = getInt(scanner.next()); // process ", classes=50002" scanner.close(); double loadFactor = (double)classes / (double)table_size; if (loadFactor > MAX_LOAD_FACTOR) { - throw new RuntimeException("Load factor too high, expected MAX "+MAX_LOAD_FACTOR+", got "+loadFactor); + + // We've hit an error, so print all of the output. + System.out.println(output); + + throw new RuntimeException("Load factor too high, expected MAX " + MAX_LOAD_FACTOR + + ", got " + loadFactor + " [table size " + table_size + ", number of clases " + classes + "]"); } else { - System.out.println("PASS table_size:"+table_size+", classes:"+classes+" OK"); + System.out.println("PASS table_size: " + table_size + ", classes: " + classes + + ", load factor: " + loadFactor + " <= " + MAX_LOAD_FACTOR); + // There are more than one system dictionary to check, so keep looking... } } - line = rd.readLine(); } - int retval = process.waitFor(); - if (retval != 0) { - throw new RuntimeException("Error: test returned non-zero value"); + + if (!resized) { + System.out.println("PASS trivially. No resizing occurred, so did not check the load."); } } public static void main(String[] args) throws Exception { if (Platform.isDebugBuild()) { + // -XX:+PrintSystemDictionaryAtExit will print the details of system dictionary, + // that will allow us to calculate the table's load factor. + // -Xlog:safepoint+cleanup will print out cleanup details at safepoint + // that will allow us to detect if the system dictionary resized. ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintSystemDictionaryAtExit", + "-Xlog:safepoint+cleanup", "TriggerResize", "50000"); analyzeOutputOn(pb); } } -} +} \ No newline at end of file diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/LdrCnstrFldMsgTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/LdrCnstrFldMsgTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @compile pkg/Grand.java pkg/Parent.java pkg/ClassLoaderForParentFoo.java + * @compile pkg/ClassLoaderForChildGrandFoo.java pkg/Child.jasm + * @run main/othervm LdrCnstrFldMsgTest + */ + +import java.lang.reflect.Method; + +// Check that LinkageError loader constraint message for fields contains the +// correct information. +// +// The test creates two class loaders. The first class loader loads classes +// Child, Foo, and Grand. The second class loader loads Parent and Foo. Class +// Parent is a sub-class of Grand and class Child is a sub-class of Parent. +// Class Child tries to load Parent._field1. This should fail because type Foo +// for Parent._field1 is a different type than Child's Foo. +// +public class LdrCnstrFldMsgTest { + public static void main(String... args) throws Exception { + ClassLoader l = new pkg.ClassLoaderForChildGrandFoo("pkg.Foo", "pkg.Child", "pkg.Grand"); + l.loadClass("pkg.Foo"); + + // Try to call a public method in Grand. + Runnable r = (Runnable) l.loadClass("pkg.Child").newInstance(); + try { + r.run(); + throw new RuntimeException("Expected LinkageError exception not thrown"); + } catch (java.lang.LinkageError e) { + if (!e.getMessage().contains("for the field's defining type, pkg.Parent,") || + !e.getMessage().contains("have different Class objects for type pkg.Foo")) { + throw new RuntimeException("Wrong LinkageError exception thrown: " + e.toString()); + } + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Child.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Child.jasm Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package pkg; + +// The getfield of Parent._field1 gets a LinkageError because class Parent +// has a different Foo class than Child, causing a loader constraint violation. +super public class Child extends pkg/Parent implements java/lang/Runnable version 50:0 { + + public Method "":"()V" stack 1 locals 1 { + aload_0; + invokespecial Method pkg/Parent."":"()V"; + return; + } + + public Method run:"()V" stack 4 locals 4 { + ldc class pkg/Foo; + astore_1; + new class pkg/Child; + dup; + invokespecial Method pkg/Child."":"()V"; + astore_2; + aload_2; + getstatic Field pkg/Parent._field1:"Lpkg/Foo;"; + pop; + return; + } + +} // end Class Child diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/ClassLoaderForChildGrandFoo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/ClassLoaderForChildGrandFoo.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package pkg; + +import java.util.*; +import java.io.*; + +// This class loader loads Foo, Child, and Grand. +public class ClassLoaderForChildGrandFoo extends ClassLoader { + + ClassLoader l2 = null; + + private final Set names = new HashSet<>(); + + public ClassLoaderForChildGrandFoo(String... names) { + for (String n : names) this.names.add(n); + } + + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + // Create class loader l2 to load Parent and Foo. And, pass this class + // loader to l2 so l2 can use it to load Grand. + if (name.contains("Parent") && l2 == null) { + l2 = new ClassLoaderForParentFoo(this, "pkg.Foo", "pkg.Grand", "pkg.Parent"); + Class b = l2.loadClass("pkg.Parent"); + return b; + } + if (!names.contains(name)) return super.loadClass(name, resolve); + Class result = findLoadedClass(name); + + if (result == null) { + String filename = name.replace('.', '/') + ".class"; + try (InputStream data = getResourceAsStream(filename)) { + if (data == null) throw new ClassNotFoundException(); + try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + int b; + do { + b = data.read(); + if (b >= 0) buffer.write(b); + } while (b >= 0); + byte[] bytes = buffer.toByteArray(); + result = defineClass(name, bytes, 0, bytes.length); + } + } catch (IOException e) { + throw new ClassNotFoundException("Error reading class file", e); + } + } + if (resolve) resolveClass(result); + return result; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/ClassLoaderForParentFoo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/ClassLoaderForParentFoo.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package pkg; + +import java.util.*; +import java.io.*; + +// This class loader loads Foo and Parent and calls back to l1 to load Grand. +public class ClassLoaderForParentFoo extends ClassLoader { + + private final Set names = new HashSet<>(); + + ClassLoader l1; + + public ClassLoaderForParentFoo(ClassLoader l, String... names) { + l1 = l; + for (String n : names) this.names.add(n); + } + + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (name.contains("Grand")) return l1.loadClass("pkg.Grand"); + if (!names.contains(name)) return super.loadClass(name, resolve); + Class result = findLoadedClass(name); + if (result == null) { + // Load our own version of Foo that will be referenced by Parent. + if (name.contains("Parent")) loadClass("pkg.Foo", resolve); + String filename = name.replace('.', '/') + ".class"; + try (InputStream data = getResourceAsStream(filename)) { + if (data == null) throw new ClassNotFoundException(); + try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + int b; + do { + b = data.read(); + if (b >= 0) buffer.write(b); + } while (b >= 0); + byte[] bytes = buffer.toByteArray(); + result = defineClass(name, bytes, 0, bytes.length); + } + } catch (IOException e) { + throw new ClassNotFoundException("Error reading class file", e); + } + } + if (resolve) resolveClass(result); + return result; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Foo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Foo.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package pkg; + +public class Foo {} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Grand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Grand.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package pkg; + +public class Grand { + public static Foo _field1; +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Parent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/ldrCnstrFldMsg/pkg/Parent.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package pkg; + +public class Parent extends Grand { + public static Foo _field1; +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java --- a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java Thu May 31 13:39:26 2018 -0700 @@ -73,7 +73,7 @@ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "show-loaders"}); output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); - output.shouldMatch("ClassLoaderData.*for "); + output.shouldMatch("CLD.*"); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "by-chunktype"}); output = new OutputAnalyzer(pb.start()); diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/exceptionMsgs/NegativeArraySizeException/NegativeArraySizeExceptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/exceptionMsgs/NegativeArraySizeException/NegativeArraySizeExceptionTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Test that NegativeArraySizeException reports the wrong size. + * @library /test/lib + * @compile NegativeArraySizeExceptionTest.java + * @run main NegativeArraySizeExceptionTest + */ + +import java.lang.reflect.Array; + +import jdk.test.lib.Asserts; + +public class NegativeArraySizeExceptionTest { + + private static void fail () throws Exception { + throw new RuntimeException("Array allocation with negative size expected to fail!"); + } + + public static void main(String[] args) throws Exception { + int minusOne = -1; + Object r = null; + + // Tests for exception thrown in arrayKlass.cp, ArrayKlass::allocate_arrayArray(). + + try { + r = new byte[minusOne][]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new Object[Integer.MIN_VALUE][]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in typeArrayKlass.cpp, TypeArrayKlass::allocate_common(). + + try { + r = new byte[minusOne]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new byte[Integer.MIN_VALUE]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in instanceKlass.cpp, InstanceKlass::allocate_objArray(). + + try { + r = new Object[minusOne]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new Object[Integer.MIN_VALUE]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in typeArrayKlass.cpp, TypeArrayKlass::allocate_common(). + // Innermost primitive array of multidimensional array has wrong size. + + try { + r = new byte[3][minusOne]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new byte[3][Integer.MIN_VALUE]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in objArrayKlass.cpp, ObjArrayKlass::allocate(). + // Innermost object array of multidimensional array has wrong size. + + try { + r = new Object[3][minusOne]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new Object[3][Integer.MIN_VALUE]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in + // Innermost primitive array of multidimensional array has wrong size. + // Outer array has size 0. + + try { + r = new byte[0][minusOne]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new byte[0][Integer.MIN_VALUE]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in + // Innermost object array of multidimensional array has wrong size. + // Outer array has size 0. + + try { + r = new Object[0][minusOne]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new Object[0][Integer.MIN_VALUE]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in objArrayKlass.cpp, ObjArrayKlass::allocate(). + // Outer array of multidimensional array has wrong size, inner array + // has primitive type. + + try { + r = new byte[minusOne][3]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new byte[Integer.MIN_VALUE][3]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in objArrayKlass.cpp, ObjArrayKlass::allocate(). + // Outer array of multidimensional array has wrong size, inner array + // has object type. + + try { + r = new Object[minusOne][3]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + r = new Object[Integer.MIN_VALUE][3]; + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + // Tests for exception thrown in reflection.cpp, Reflection::reflect_new_array(). + + try { + Array.newInstance(byte.class, minusOne); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(byte.class, Integer.MIN_VALUE); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + try { + Array.newInstance(NegativeArraySizeException.class, minusOne); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(NegativeArraySizeException.class, Integer.MIN_VALUE); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + + // Tests for exception thrown in reflection.cpp, Reflection::reflect_new_multi_array(). + + try { + Array.newInstance(byte.class, new int[] {3, minusOne}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(byte.class, new int[] {3, Integer.MIN_VALUE}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + try { + Array.newInstance(byte.class, new int[] {0, minusOne}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(byte.class, new int[] {0, Integer.MIN_VALUE}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + try { + Array.newInstance(NegativeArraySizeException.class, new int[] {3, minusOne}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(NegativeArraySizeException.class, new int[] {3, Integer.MIN_VALUE}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + try { + Array.newInstance(byte.class, new int[] {minusOne, 3}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(byte.class, new int[] {Integer.MIN_VALUE, 3}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + try { + Array.newInstance(NegativeArraySizeException.class, new int[] {minusOne, 3}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-1", e.getMessage()); + } + + try { + Array.newInstance(NegativeArraySizeException.class, new int[] {Integer.MIN_VALUE, 3}); + fail(); + } catch (NegativeArraySizeException e) { + Asserts.assertEQ("-2147483648", e.getMessage()); + } + + Asserts.assertEQ(r, null, "Expected all tries to allocate negative array to fail."); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java --- a/test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8139564 + * @bug 8139564 8203960 * @summary defaultmethods=debug should have logging from each of the statements in the code * @library /test/lib * @modules java.base/jdk.internal.misc @@ -50,7 +50,15 @@ output.shouldHaveExitValue(0); } - public static class InnerClass { + interface TestInterface { + default void doSomething() { + System.out.println("Default TestInterface"); + } + } + + public static class InnerClass implements TestInterface { + // InnerClass implements TestInterface with a default method. + // Loading of InnerClass will trigger default method processing. public static void main(String[] args) throws Exception { System.out.println("Inner Class"); } diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider01/AttachProvider01.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider01/AttachProvider01.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/AttachProvider/AttachProvider01. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks that method AttachProvider.listVirtualMachines() returns + * VirtualMachineDescriptors for 2 VMs started by this test. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.AttachProvider.AttachProvider01.AttachProvider01 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.AttachProvider.AttachProvider01.AttachProvider01 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.AttachProvider.AttachProvider01; + +import java.util.List; +import com.sun.tools.attach.*; +import com.sun.tools.attach.spi.AttachProvider; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +/* + * Test checks method AttachProvider.listVirtualMachines() + * (test checks that collection returned by AttachProvider.listVirtualMachines() contains current VM + * and another VM started by this test) + */ +public class AttachProvider01 extends AODTestRunner { + + public AttachProvider01(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + String currentVMId = getCurrentVMId(); + + for (AttachProvider provider : AttachProvider.providers()) { + log.display("Checking AttachProvider.listVirtualMachines() (provider: " + provider + ")"); + checkList(provider.listVirtualMachines(), currentVMId, targetVMId); + } + } + + private void checkList(List vmDescriptors, String currentVMId, String targetVMId) { + VirtualMachineDescriptor currentVMDesc = null; + VirtualMachineDescriptor targetVMDesc = null; + + for (VirtualMachineDescriptor vmDescriptor : VirtualMachine.list()) { + log.display("VirtualMachineDescriptor: " + vmDescriptor); + + if (vmDescriptor.id().equals(currentVMId)) { + currentVMDesc = vmDescriptor; + } else if (vmDescriptor.id().equals(targetVMId)) { + targetVMDesc = vmDescriptor; + } + } + + TestUtils.assertNotNull(currentVMDesc, "VirtualMachine.list() didn't return descriptor for the current VM"); + TestUtils.assertNotNull(targetVMDesc, "VirtualMachine.list() didn't return descriptor for VM with id '" + + targetVMId + "'"); + } + + public static void main(String[] args) { + new AttachProvider01(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider02/AttachProvider02.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider02/AttachProvider02.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/AttachProvider/AttachProvider02. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test tries to attach to the VM started by this test using 2 methods: + * - AttachProvider.attachVirtualMachine(String id) + * - AttachProvider.attachVirtualMachine(VirtualMachineDescriptor vmd) + * After attaching test tries to use created VirtualMachine object (tries to call VirtualMachine.getSystemProperties()). + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.AttachProvider.AttachProvider02.AttachProvider02 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -Djdk.attach.allowAttachSelf -XX:+UsePerfData + * PropertyResolvingWrapper + * nsk.aod.AttachProvider.AttachProvider02.AttachProvider02 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.AttachProvider.AttachProvider02; + +import java.util.Properties; +import com.sun.tools.attach.*; +import com.sun.tools.attach.spi.AttachProvider; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +/* + * Test checks following methods: + * - AttachProvider.attachVirtualMachine(String id) + * - AttachProvider.attachVirtualMachine(VirtualMachineDescriptor vmd) + */ +public class AttachProvider02 extends AODTestRunner { + + public AttachProvider02(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + TestUtils.assertTrue(AttachProvider.providers().size() > 0, "Method AttachProvider.providers() returns empty collection"); + + String currentVMId = getCurrentVMId(); + + for (AttachProvider provider : AttachProvider.providers()) { + log.display("Provider: " + provider); + log.display("Provider.name(): " + provider.name()); + log.display("Provider.type(): " + provider.type()); + + TestUtils.assertNotNull(provider.name(), "Provider.name() returns null"); + TestUtils.assertNotNull(provider.type(), "Provider.type() returns null"); + + tryAttach(provider, currentVMId, false); + + tryAttach(provider, currentVMId, true); + + tryAttach(provider, targetVMId, false); + + tryAttach(provider, targetVMId, true); + } + } + + void tryAttach(AttachProvider provider, String vmId, boolean useVMDescriptor) throws Throwable { + log.display("Attaching to vm " + vmId + " using " + + (useVMDescriptor ? "VirtualMachineDescriptor " : "VM id")); + + VirtualMachine vm; + + if (useVMDescriptor) + vm = provider.attachVirtualMachine(new VirtualMachineDescriptor(provider, vmId)); + else + vm = provider.attachVirtualMachine(vmId); + + try { + log.display("Attached to vm: " + vm); + TestUtils.assertEquals(vm.id(), vmId, "VirtualMachine.id() returns unexpected value for attached vm: " + vm.id()); + + // try to use created VirtualMachine + + log.display("Trying to call VirtualMachine.getSystemProperties()"); + Properties properties = vm.getSystemProperties(); + TestUtils.assertNotNull(properties, "VirtualMachine.getSystemProperties() returns null"); + + TestUtils.assertTrue(properties.size() > 0, "VirtualMachine.getSystemProperties() returns empty collection"); + } finally { + vm.detach(); + } + } + + public static void main(String[] args) { + new AttachProvider02(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine01/VirtualMachine01.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine01/VirtualMachine01.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine01. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * Test checks that methods of VirtualMachine throws expected exceptions + * in following cases: + * - VirtualMachine.attach(null) should throw NullPointerException + * - VirtualMachine.attach() should throw AttachNotSupportedException + * - VirtualMachine.loadAgent(null), VirtualMachine.loadAgentLibrary(null), + * VirtualMachine.loadAgentPath(null) should throw NullPointerException + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine01.VirtualMachine01 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine01.VirtualMachine01 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.VirtualMachine.VirtualMachine01; + +import nsk.share.aod.*; +import nsk.share.test.TestUtils; +import com.sun.tools.attach.*; +import com.sun.tools.attach.spi.AttachProvider; + +/* + * Test provokes exception which should be thrown by VirtualMachine methods: + * - VirtualMachine.attach(null) should throw NullPointerException + * - VirtualMachine.attach() should throw AttachNotSupportedException + * - VirtualMachine.loadAgent(null), VirtualMachine.loadAgentLibrary(null), + * VirtualMachine.loadAgentPath(null) should throw NullPointerException + */ +public class VirtualMachine01 extends AODTestRunner { + + VirtualMachine01(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + try { + log.display("VirtualMachine.attach((String)null)"); + VirtualMachine.attach((String) null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + try { + log.display("VirtualMachine.attach((VirtualMachineDescriptor)null)"); + VirtualMachine.attach((VirtualMachineDescriptor) null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + final String invalidVMId = "InvalidID"; + + try { + log.display("VirtualMachine.attach(" + invalidVMId + ")"); + VirtualMachine.attach(invalidVMId); + TestUtils.testFailed("AttachNotSupportedException wasn't thrown"); + } catch (AttachNotSupportedException e) { + log.display("Expected exception: " + e); + } + + try { + TestUtils.assertTrue(AttachProvider.providers().size() > 0, "AttachProvider.providers() returns empty list"); + log.display("Create VirtualMachineDescriptor using provider '" + AttachProvider.providers().get(0) + "'"); + VirtualMachineDescriptor vmd = new VirtualMachineDescriptor(AttachProvider.providers().get(0), invalidVMId); + log.display("VirtualMachine.attach(new VirtualMachineDescriptor(provider, " + invalidVMId + "))"); + VirtualMachine.attach(vmd); + TestUtils.testFailed("AttachNotSupportedException wasn't thrown"); + } catch (AttachNotSupportedException e) { + log.display("Expected exception: " + e); + } + + // create VirtualMachine object VM to check non-static methods + + VirtualMachine vm = VirtualMachine.attach(targetVMId); + try { + try { + log.display("VirtualMachine.loadAgent(null)"); + vm.loadAgent(null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + try { + log.display("VirtualMachine.loadAgent(null, null)"); + vm.loadAgent(null, null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + try { + log.display("VirtualMachine.loadAgentLibrary(null)"); + vm.loadAgentLibrary(null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + try { + log.display("VirtualMachine.loadAgentLibrary(null, null)"); + vm.loadAgentLibrary(null, null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + try { + log.display("VirtualMachine.loadAgentPath(null)"); + vm.loadAgentPath(null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + try { + log.display("VirtualMachine.loadAgentPath(null, null)"); + vm.loadAgentPath(null, null); + TestUtils.testFailed("NullPointerException wasn't thrown"); + } catch (NullPointerException e) { + log.display("Expected exception: " + e); + } + + } finally { + vm.detach(); + } + } + + public static void main(String[] args) { + new VirtualMachine01(args).runTest(); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine02/VirtualMachine02.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine02/VirtualMachine02.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine02. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * Test checks following methods: + * - VirtualMachine.attach(String id) (test tries to attach to the VM running test + * and to the another VM started by this test) + * - VirtualMachine.attach(VirtualMachineDescriptor vmd) (test tries to attach to the VM running test + * and to the another VM started by this test) + * - VirtualMachine.detach() (test checks that after detaching operations on VirtualMachine throw IOException) + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine02.VirtualMachine02 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -Djdk.attach.allowAttachSelf -XX:+UsePerfData + * PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine02.VirtualMachine02 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.VirtualMachine.VirtualMachine02; + +import java.io.IOException; +import com.sun.tools.attach.*; +import com.sun.tools.attach.spi.AttachProvider; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +/* + * Test checks following methods: + * - VirtualMachine.attach(String) (test tries to attach to current and to another VM) + * + * - VirtualMachine.attach(VirtualMachineDescriptor) (test tries to attach to current and to another VM) + * + * - VirtualMachine.detach() (test checks that after detaching operations on VirtualMachine + * throw IOException) + */ +public class VirtualMachine02 extends AODTestRunner { + + public VirtualMachine02(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + log.display("Executing test for current VM"); + String currentVMId = getCurrentVMId(); + doTest(currentVMId); + log.display(""); + + log.display("Executing test for another VM (id = " + targetVMId + ")"); + doTest(targetVMId); + } + + void doTest(String targetVMId) throws Throwable { + VirtualMachine vm; + + log.display("Trying to attach using VirtualMachine(\"" + targetVMId + "\")"); + vm = VirtualMachine.attach(targetVMId); + log.display("Attached: " + vm); + checkDetach(vm); + + log.display("Trying to attach using VirtualMachine(VirtualMachineDescriptor)"); + AttachProvider provider; + TestUtils.assertTrue(AttachProvider.providers().size() > 0, "AttachProvider.providers() returns empty list"); + provider = AttachProvider.providers().get(0); + log.display("Create VirtualMachineDescriptor using provider '" + provider + "'"); + VirtualMachineDescriptor vmDescriptor = new VirtualMachineDescriptor(provider, targetVMId); + vm = VirtualMachine.attach(vmDescriptor); + log.display("Attached: " + vm); + TestUtils.assertEquals(vm.provider(), provider, "vm.provider() returns unexpected value: " + vm.provider()); + checkDetach(vm); + } + + void checkDetach(VirtualMachine vm) throws Throwable { + log.display("Detaching from " + vm); + vm.detach(); + + try { + vm.getSystemProperties(); + TestUtils.testFailed("Expected IOException wasn't thrown"); + } catch (IOException e) { + // expected exception + } + try { + vm.getAgentProperties(); + TestUtils.testFailed("Expected IOException wasn't thrown"); + } catch (IOException e) { + // expected exception + } + try { + vm.loadAgent("agent"); + TestUtils.testFailed("Expected IOException wasn't thrown"); + } catch (IOException e) { + // expected exception + } + try { + vm.loadAgentLibrary("agent"); + TestUtils.testFailed("Expected IOException wasn't thrown"); + } catch (IOException e) { + // expected exception + } + try { + vm.loadAgentPath("agent"); + TestUtils.testFailed("Expected IOException wasn't thrown"); + } catch (IOException e) { + // expected exception + } + + // shouldn't throw exception + log.display("Trying to call detach one more time for " + vm); + vm.detach(); + } + + public static void main(String[] args) { + new VirtualMachine02(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine03/VirtualMachine03.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine03/VirtualMachine03.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine03. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * Test checks semantics of the method VirtualMachine.equals(Object obj). + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine03.VirtualMachine03 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -Djdk.attach.allowAttachSelf -XX:+UsePerfData + * PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine03.VirtualMachine03 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.VirtualMachine.VirtualMachine03; + +import com.sun.tools.attach.VirtualMachine; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +/* + * Test checks method VirtualMachine.equals(Object) + */ +public class VirtualMachine03 extends AODTestRunner { + + public VirtualMachine03(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + String currentVMId = getCurrentVMId(); + + VirtualMachine vm1 = VirtualMachine.attach(currentVMId); + + VirtualMachine vm2 = VirtualMachine.attach(targetVMId); + + try { + TestUtils.assertEquals(vm1.id(), currentVMId, "vm.id() returns unexpected value: " + vm1.id()); + + TestUtils.assertEquals(vm2.id(), targetVMId, "vm.id() returns unexpected value: " + vm2.id()); + + TestUtils.assertTrue(!vm1.equals(vm2), vm1 + ".equals(" + vm2 + ") returns 'true'"); + + checkVM(vm1); + + checkVM(vm2); + } finally { + vm1.detach(); + + vm2.detach(); + } + } + + void checkVM(VirtualMachine vm1) throws Throwable { + TestUtils.assertEquals(vm1, vm1, "vm.equals(itself) returns 'false'"); + + // create one more VirtualMachine object for the same VM + VirtualMachine vm2 = VirtualMachine.attach(vm1.id()); + try { + TestUtils.assertEquals(vm1, vm2, vm1 + ".equals(" + vm2 + ") returns 'false'"); + + TestUtils.assertTrue(vm1.hashCode() == vm2.hashCode(), "vm.hashCode() returns different values for " + vm1 + " and " + vm2); + + TestUtils.assertEquals(vm1.provider(), vm2.provider(), "vm.provider() returns non-equals objects for " + vm1 + " and " + vm2); + } finally { + vm2.detach(); + } + + TestUtils.assertTrue(!vm1.equals(new String()), "vm.equals(String) returns 'true'"); + + TestUtils.assertTrue(!vm1.equals(null), "vm.equals(null) returns 'true'"); + } + + public static void main(String[] args) { + new VirtualMachine03(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VM04Target.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VM04Target.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.aod.VirtualMachine.VirtualMachine04; + +import nsk.share.TestBug; +import nsk.share.aod.DummyTargetApplication; + +/* + * This target application during initialization sets special system property, + * main test application tries to get this property using VirtualMachine.getSystemProperties() + */ +public class VM04Target extends DummyTargetApplication { + + static String testPropertyKey = "VirtualMachine04_testPropertyKey"; + + static String testPropertyValue = "VirtualMachine04_testPropertyValue"; + + static String changedTestPropertyValue = "VirtualMachine04_testPropertyValue_changed"; + + VM04Target(String[] args) { + super(args); + + log.display("Setting property " + testPropertyKey + " = " + testPropertyValue); + System.setProperty(testPropertyKey, testPropertyValue); + } + + protected void targetApplicationActions() { + String signal = pipe.readln(); + log.display("Received signal: " + signal); + if (!signal.equals(VirtualMachine04.SIGNAL_CHANGE_PROPERTY)) + throw new TestBug("Received unexpected signal: " + signal); + + log.display("Setting property " + testPropertyKey + " = " + changedTestPropertyValue); + System.setProperty(testPropertyKey, changedTestPropertyValue); + + log.display("Sending signal " + VirtualMachine04.SIGNAL_PROPERTY_CHANGED); + pipe.println(VirtualMachine04.SIGNAL_PROPERTY_CHANGED); + } + + public static void main(String[] args) { + new VM04Target(args).runTargetApplication(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VirtualMachine04.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VirtualMachine04.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine04. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * Test checks following methods: + * - VirtualMachine.getSystemProperties() (test checks that returned properties contains + * expected property and tested method returns properties whose key and value is a String) + * - VirtualMachine.getAgentProperties() (test checks that method returns properties whose + * key and value is a String) + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine04.VirtualMachine04 + * nsk.aod.VirtualMachine.VirtualMachine04.VM04Target + * @run main/othervm -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine04.VirtualMachine04 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.aod.VirtualMachine.VirtualMachine04.VM04Target + */ + +package nsk.aod.VirtualMachine.VirtualMachine04; + +import java.util.Properties; +import com.sun.tools.attach.VirtualMachine; +import nsk.share.aod.AODTestRunner; +import nsk.share.test.TestUtils; +import nsk.share.*; + +/* + * Test checks following methods: + * - VirtualMachine.getSystemProperties() + * + * - VirtualMachine.getAgentProperties() + */ +public class VirtualMachine04 extends AODTestRunner { + + static final String SIGNAL_CHANGE_PROPERTY = "change_property"; + + static final String SIGNAL_PROPERTY_CHANGED = "property_changed"; + + public VirtualMachine04(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + VirtualMachine vm = VirtualMachine.attach(targetVMId); + + try { + checkSystemProperties(vm, VM04Target.testPropertyKey, VM04Target.testPropertyValue); + + log.display("Sending signal " + SIGNAL_CHANGE_PROPERTY); + pipe.println(SIGNAL_CHANGE_PROPERTY); + String signal = pipe.readln(); + log.display("Received signal " + signal); + if (!signal.equals(SIGNAL_PROPERTY_CHANGED)) + throw new TestBug("Unexpected signal received: " + signal); + + checkSystemProperties(vm, VM04Target.testPropertyKey, VM04Target.changedTestPropertyValue); + + Properties properties = vm.getAgentProperties(); + System.out.println("VirtualMachine.getAgentProperties(): " + properties); + checkProperties(properties); + } finally { + vm.detach(); + } + } + + void checkSystemProperties(VirtualMachine vm, + String propertyToCheck, + String expectedPropertyValue) throws Throwable { + + Properties properties = vm.getSystemProperties(); + System.out.println("VirtualMachine.getSystemProperties(): " + properties); + checkProperties(properties); + + String checkedPropertyValue = properties.getProperty(propertyToCheck); + TestUtils.assertNotNull(checkedPropertyValue, "Properties doesn't contain property '" + propertyToCheck + "'"); + TestUtils.assertEquals(checkedPropertyValue, expectedPropertyValue, + "Unexpected value of the property '" + propertyToCheck + "': " + checkedPropertyValue + ", expected value is '" + expectedPropertyValue + "'"); + } + + /* + * Check following spec clause: VirtualMachine.getSystemProperties() and + * VirtualMachine.getAgentProperties() return the properties whose key and value is a String + */ + void checkProperties(Properties properties) { + TestUtils.assertNotNull(properties, "Method returns null Properties"); + + for (Object key : properties.keySet()) { + Object value = properties.get(key); + log.display("Value of '" + key + "' = " + value); + + TestUtils.assertTrue(key instanceof String, "Property key isn't String: " + key.getClass().getName()); + + TestUtils.assertTrue(value instanceof String, "Property value isn't String: " + value.getClass().getName()); + } + } + + public static void main(String[] args) { + new VirtualMachine04(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine05/VirtualMachine05.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine05/VirtualMachine05.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine05. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks that method VirtualMachine.list() returns + * VirtualMachineDescriptors for 2 VMs started by this test. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine05.VirtualMachine05 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine05.VirtualMachine05 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.VirtualMachine.VirtualMachine05; + +import java.util.List; +import com.sun.tools.attach.*; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +/* + * Test checks method VirtualMachine.list() + * (test checks that collection returned by VirtualMachine.list() contains current VM + * and another VM started by this test) + */ +public class VirtualMachine05 extends AODTestRunner { + + public VirtualMachine05(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + String currentVMId = getCurrentVMId(); + + log.display("Checking VirtualMachine.list()"); + checkList(VirtualMachine.list(), currentVMId, targetVMId); + } + + private void checkList(List vmDescriptors, String currentVMId, String targetVMId) { + VirtualMachineDescriptor currentVM = null; + VirtualMachineDescriptor targetVM = null; + + for (VirtualMachineDescriptor vmDescriptor : VirtualMachine.list()) { + log.display("VirtualMachineDescriptor: " + vmDescriptor); + + if (vmDescriptor.id().equals(currentVMId)) { + currentVM = vmDescriptor; + } else if (vmDescriptor.id().equals(targetVMId)) { + targetVM = vmDescriptor; + } + } + + TestUtils.assertNotNull(currentVM, "VirtualMachine.list() didn't return descriptor for the current VM"); + + TestUtils.assertNotNull(targetVM, "VirtualMachine.list() didn't return descriptor for VM with id '" + + targetVMId + "'"); + } + + public static void main(String[] args) { + new VirtualMachine05(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent00.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent00.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.aod.VirtualMachine.VirtualMachine06; + +import java.lang.instrument.Instrumentation; + +import nsk.share.aod.TargetApplicationWaitingAgents; + +public class VM06Agent00 { + public static void agentmain(String options, Instrumentation inst) { + boolean success = true; + + TargetApplicationWaitingAgents.agentLoaded(VM06Agent00.class.getName()); + try { + System.out.println("Agent options: " + options); + if (options != null) { + success = false; + System.out.println("ERROR: unexpected non-null options"); + } + } catch (Throwable t) { + success = false; + System.out.println("Unexpected exception: " + t); + } finally { + TargetApplicationWaitingAgents.agentFinished(VM06Agent00.class.getName(), success); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent00.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent00.mf Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Agent-Class: nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent00 diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent01.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent01.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.aod.VirtualMachine.VirtualMachine06; + +import java.lang.instrument.Instrumentation; + +import nsk.share.aod.TargetApplicationWaitingAgents; + +public class VM06Agent01 { + public static void agentmain(String options, Instrumentation inst) { + boolean success = true; + + TargetApplicationWaitingAgents.agentLoaded(VM06Agent01.class.getName()); + try { + System.out.println("Agent options: " + options); + if (options != null) { + success = false; + System.out.println("ERROR: unexpected non-null options"); + } + } catch (Throwable t) { + success = false; + System.out.println("Unexpected exception: " + t); + } finally { + TargetApplicationWaitingAgents.agentFinished(VM06Agent01.class.getName(), success); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent01.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent01.mf Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Agent-Class: nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent01 diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent02.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent02.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.aod.VirtualMachine.VirtualMachine06; + +import java.lang.instrument.Instrumentation; + +import nsk.share.aod.TargetApplicationWaitingAgents; + +public class VM06Agent02 { + public static void agentmain(String options, Instrumentation inst) { + boolean success = true; + + TargetApplicationWaitingAgents.agentLoaded(VM06Agent02.class.getName()); + try { + System.out.println("Agent options: " + options); + if (options == null || !options.equals("VirtualMachine06_TestOptions")) { + success = false; + System.out.println("ERROR: unexpected non-null options"); + } + } catch (Throwable t) { + success = false; + System.out.println("Unexpected exception: " + t); + } finally { + TargetApplicationWaitingAgents.agentFinished(VM06Agent02.class.getName(), success); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent02.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent02.mf Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Agent-Class: nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent02 diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent03.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent03.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.aod.VirtualMachine.VirtualMachine06; + +import java.lang.instrument.Instrumentation; + +import nsk.share.aod.TargetApplicationWaitingAgents; + +public class VM06Agent03 { + public static void agentmain(String options, Instrumentation inst) { + TargetApplicationWaitingAgents.agentLoaded(VM06Agent03.class.getName()); + TargetApplicationWaitingAgents.agentFinished(VM06Agent03.class.getName(), true); + + throw new RuntimeException("Test exception"); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent03.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent03.mf Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Agent-Class: nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent03 diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VirtualMachine06.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VirtualMachine06.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine06. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks methods VirtualMachine.loadAgent(String agent) and + * VirtualMachine.loadAgent(String agent, String options). + * Test checks following cases: + * - it is possible to pass options to agent using loadAgent(String agent, String options) + * - it is possible to specify null options (in this case null is passed to the agentmain) + * - if agent throws exception from 'agentmain' VirtualMachine.loadAgent throws AgentInitializationException + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment compile VM06Agent0[0-3].java to current directory + * @build nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent00 + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent01 + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent02 + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent03 + * @run driver ClassFileInstaller + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent00 + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent01 + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent02 + * nsk.aod.VirtualMachine.VirtualMachine06.VM06Agent03 + * + * @comment create VM06Agent0[0-3].jar in current directory + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --cmd + * ${test.jdk}/bin/jar -cmf VM06Agent00.mf VM06Agent00.jar + * nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent00.class + * @run driver PropertyResolvingWrapper ExecDriver --cmd + * ${test.jdk}/bin/jar -cmf VM06Agent01.mf VM06Agent01.jar + * nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent01.class + * @run driver PropertyResolvingWrapper ExecDriver --cmd + * ${test.jdk}/bin/jar -cmf VM06Agent02.mf VM06Agent02.jar + * nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent02.class + * @run driver PropertyResolvingWrapper ExecDriver --cmd + * ${test.jdk}/bin/jar -cmf VM06Agent03.mf VM06Agent03.jar + * nsk/aod/VirtualMachine/VirtualMachine06/VM06Agent03.class + * + * + * @build nsk.aod.VirtualMachine.VirtualMachine06.VirtualMachine06 + * nsk.share.aod.TargetApplicationWaitingAgents + * @run main/othervm -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine06.VirtualMachine06 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.TargetApplicationWaitingAgents + * -ja VM06Agent00.jar,VM06Agent01.jar,VM06Agent02.jar,VM06Agent03.jar + */ + +package nsk.aod.VirtualMachine.VirtualMachine06; + +import nsk.share.TestBug; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; +import java.util.*; +import com.sun.tools.attach.*; + +/* + * Test checks following methods: + * - VirtualMachine.loadAgent(String) + * + * - VirtualMachine.loadAgent(String, String) + */ +public class VirtualMachine06 extends AODTestRunner { + + public VirtualMachine06(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + // check that all required parameters were passed to the test + List agents = argParser.getAgents(); + if (agents.size() != 4) + throw new TestBug("Test requires 4 agents, actually " + agents.size() + " were specified"); + + for (AgentInformation agent : agents) { + if (!agent.jarAgent) + throw new TestBug("Non JAR agent was specified"); + } + + VirtualMachine vm = VirtualMachine.attach(targetVMId); + + try { + AgentInformation agent; + + agent = agents.get(0); + log.display("Loading '" + agent.pathToAgent + "'"); + // pass null options to agent + vm.loadAgent(agent.pathToAgent); + + agent = agents.get(1); + log.display("Loading '" + agent.pathToAgent + "'"); + // pass null options to agent + vm.loadAgent(agent.pathToAgent, null); + + agent = agents.get(2); + log.display("Loading '" + agent.pathToAgent + "'"); + // pass non-null options to agent + vm.loadAgent(agent.pathToAgent, "VirtualMachine06_TestOptions"); + + agent = agents.get(3); + log.display("Loading '" + agent.pathToAgent + "' (this agent throws exception from agentmain)"); + try { + // check agent throwing exception from agentmain + vm.loadAgent(agent.pathToAgent); + TestUtils.testFailed("Expected AgentInitializationException wasn't thrown"); + } catch (AgentInitializationException e) { + // expected exception + } + } finally { + vm.detach(); + } + } + + public static void main(String[] args) { + new VirtualMachine06(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/VirtualMachine07.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/VirtualMachine07.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine07. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks methods VirtualMachine.loadAgentLibrary(String agent) and + * VirtualMachine.loadAgentLibrary(String agent, String options). + * Test checks following cases: + * - it is possible to pass options to agent using loadAgentLibrary(String agent, String options) + * - it is possible to specify null options (in this case zero-length is passed to the Agent_OnAttach) + * - if Agent_OnAttach returns error code loadAgentLibrary throws AgentInitializationException and + * AgentInitializationException.returnValue() returns this error code + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07 + * nsk.share.aod.TargetApplicationWaitingAgents + * @run main/othervm/native -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.TargetApplicationWaitingAgents + * -na VirtualMachine07agent00,VirtualMachine07agent01,VirtualMachine07agent02,VirtualMachine07agent03 + * -testedMethod loadAgentLibrary + */ + +package nsk.aod.VirtualMachine.VirtualMachine07; + +import nsk.share.*; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +import java.util.*; + +import com.sun.tools.attach.*; + +/* + * Test is written to test following methods: + * - VirtualMachine.loadAgentLibrary + * + * - VirtualMachine.loadAgentPath + * + *(method to test is specified via command line parameter 'testedMethod') + */ +public class VirtualMachine07 extends AODTestRunner { + + static class ArgParser extends AODRunnerArgParser { + + final String testedMethodOpt = "testedMethod"; + + ArgParser(String[] args) { + super(args); + } + + protected boolean checkOption(String option, String value) { + if (super.checkOption(option, value)) + return true; + + if (option.equals(testedMethodOpt)) { + if (value.equals("loadAgentLibrary") || value.equals("loadAgentPath")) + return true; + else + throw new TestBug("Unexpected value of '" + testedMethodOpt + "': " + value); + } + + return false; + } + + protected void checkOptions() { + super.checkOptions(); + + // if test loadAgentPath parameter arch is needed + if (!testLoadAgentLibrary()) { + if (!options.containsKey("arch")) + throw new TestBug("Option 'arch' wasn't specified"); + } + } + + boolean testLoadAgentLibrary() { + return options.getProperty(testedMethodOpt).equals("loadAgentLibrary"); + } + } + + public VirtualMachine07(String[] args) { + super(args); + } + + /* + * When test method loadAgentPath platform specific agent name should be + * created (lib.so for unix, lib.dylib for macosx and + * .dll for windows) + */ + protected String expandAgentPath(String path) { + int index = path.lastIndexOf('/'); + if (index < 0) + throw new TestBug("Unexpected agent library name format"); + + String dir = path.substring(0, index); + String libName = path.substring(index + 1); + + if (argParser.getArch().startsWith("windows")) { + return dir + "/" + libName + ".dll"; + } else if (argParser.getArch().startsWith("mac")) { + return dir + "/" + "lib" + libName + ".dylib"; + } else { + return dir + "/" + "lib" + libName + ".so"; + } + } + + protected AODRunnerArgParser createArgParser(String[] args) { + return new ArgParser(args); + } + + protected void loadAgent(VirtualMachine vm, String agent) throws Throwable { + boolean testLoadAgentLibrary = ((ArgParser) argParser).testLoadAgentLibrary(); + + if (testLoadAgentLibrary) + log.display("Test method VirtualMachine.loadAgentLibrary"); + else + log.display("Test method VirtualMachine.loadAgentPath"); + + if (testLoadAgentLibrary) { + log.display("Loading '" + agent + "'"); + vm.loadAgentLibrary(agent); + } else { + String expandedName = (agent == null ? null : expandAgentPath(agent)); + log.display("Loading '" + expandedName + "'"); + vm.loadAgentPath(expandedName); + } + } + + protected void loadAgent(VirtualMachine vm, String agent, String options) throws Throwable { + boolean testLoadAgentLibrary = ((ArgParser) argParser).testLoadAgentLibrary(); + + if (testLoadAgentLibrary) + log.display("Test method VirtualMachine.loadAgentLibrary"); + else + log.display("Test method VirtualMachine.loadAgentPath"); + + if (testLoadAgentLibrary) { + log.display("Loading '" + agent + "'"); + vm.loadAgentLibrary(agent, options); + } else { + String expandedName = (agent == null ? null : expandAgentPath(agent)); + log.display("Loading '" + expandedName + "'"); + vm.loadAgentPath(expandedName, options); + } + } + + public void doTestActions(String targetVMId) throws Throwable { + // check that all required parameters were passed to the test + List agents = argParser.getAgents(); + if (agents.size() != 4) + throw new TestBug("Test requires 4 agents, actually " + agents.size() + " were specified"); + + for (AgentInformation agent : agents) { + if (agent.jarAgent) + throw new TestBug("Non native agent was specified"); + } + + VirtualMachine vm = VirtualMachine.attach(targetVMId); + + try { + AgentInformation agent; + + agent = agents.get(0); + loadAgent(vm, agent.pathToAgent); + + agent = agents.get(1); + loadAgent(vm, agent.pathToAgent, null); + + agent = agents.get(2); + loadAgent(vm, agent.pathToAgent, "VirtualMachine_TestOptions"); + + agent = agents.get(3); + log.display("Loading '" + agent.pathToAgent + "' (this agent fails to initialize)"); + try { + loadAgent(vm, agent.pathToAgent); + + TestUtils.testFailed("Expected AgentInitializationException wasn't thrown"); + } catch (AgentInitializationException e) { + log.display("Expected AgentInitializationException was caught"); + log.display("AgentInitializationException.returnValue(): " + e.returnValue()); + TestUtils.assertEquals(e.returnValue(), 10, + "AgentInitializationException.returnValue() returns unexpected value: " + e.returnValue()+ ", expected value is 10"); + } + } finally { + vm.detach(); + } + } + + public static void main(String[] args) { + new VirtualMachine07(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent00.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent00.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AGENT_NAME "VMNativeAgent00" + +JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved) { + JNIEnv* jni; + int success = 1; + + // can't use NSK_DISPLAY since needed for nsk_ functions initialization isn't done here + + if ((jni = (JNIEnv*) nsk_aod_createJNIEnv(vm)) == NULL) + return JNI_ERR; + + printf("%s: initialization was done\n", AGENT_NAME); + fflush(stdout); + + if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, AGENT_NAME))) + return JNI_ERR; + + if (optionsString == NULL) { + success = 0; + printf("%s: ERROR: unexpected null options\n", AGENT_NAME); + fflush(stdout); + } else { + size_t length = strlen(optionsString); + if (length != 0) { + success = 0; + printf("%s: ERROR: unexpected non-zero length options string: '%s'\n", AGENT_NAME, optionsString); + fflush(stdout); + } + } + + nsk_aod_agentFinished(jni, AGENT_NAME, success); + + return JNI_OK; +} + +#ifdef __cplusplus +} +#endif diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent01.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent01.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AGENT_NAME "VMNativeAgent01" + +/* + */ + +JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved) { + JNIEnv* jni; + int success = 1; + + // can't use NSK_DISPLAY since needed for nsk_ functions initialization isn't done here + + if ((jni = (JNIEnv*) nsk_aod_createJNIEnv(vm)) == NULL) + return JNI_ERR; + + printf("%s: initialization was done\n", AGENT_NAME); + fflush(stdout); + + if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, AGENT_NAME))) + return JNI_ERR; + + if (optionsString == NULL) { + success = 0; + printf("%s: ERROR: unexpected null options\n", AGENT_NAME); + fflush(stdout); + } else { + size_t length = strlen(optionsString); + if (length != 0) { + success = 0; + printf("%s: ERROR: unexpected non-zero length options string: '%s'\n", AGENT_NAME, optionsString); + fflush(stdout); + } + } + + nsk_aod_agentFinished(jni, AGENT_NAME, success); + + return JNI_OK; +} + +#ifdef __cplusplus +} +#endif diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent02.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent02.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AGENT_NAME "VMNativeAgent02" + +#define EXPECTED_OPTIONS "VirtualMachine_TestOptions" + +/* + */ + +JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved) { + JNIEnv* jni; + int success = 1; + + // can't use NSK_DISPLAY since needed for nsk_ functions initialization isn't done here + + if ((jni = (JNIEnv*) nsk_aod_createJNIEnv(vm)) == NULL) + return JNI_ERR; + + printf("%s: initialization was done\n", AGENT_NAME); + fflush(stdout); + + if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, AGENT_NAME))) + return JNI_ERR; + + if (optionsString == NULL) { + success = 0; + printf("%s: ERROR: unexpected null options\n", AGENT_NAME); + fflush(stdout); + } else { + if (strcmp(optionsString, EXPECTED_OPTIONS)) { + success = 0; + printf("%s: ERROR: unexpected options string: '%s', expected is '%s'\n", + AGENT_NAME, optionsString, EXPECTED_OPTIONS); + fflush(stdout); + } + } + + nsk_aod_agentFinished(jni, AGENT_NAME, success); + + return JNI_OK; +} + +#ifdef __cplusplus +} +#endif diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent03.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/agent03.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AGENT_NAME "VMNativeAgent03" + +#define ON_ATTACH_EXIT_CODE 10 + +/* + */ + +JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved) { + JNIEnv* jni; + + if ((jni = (JNIEnv*) nsk_aod_createJNIEnv(vm)) == NULL) + return JNI_ERR; + + // can't use NSK_DISPLAY since needed for nsk_ functions initialization isn't done here + + printf("%s: initialization was done\n", AGENT_NAME); + fflush(stdout); + + if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, AGENT_NAME))) + return JNI_ERR; + + nsk_aod_agentFinished(jni, AGENT_NAME, 1); + + printf("%s: warning: agent is intentionally exiting from Agent_OnAttach with error code %d\n", AGENT_NAME, ON_ATTACH_EXIT_CODE); + fflush(stdout); + + return ON_ATTACH_EXIT_CODE; +} + +#ifdef __cplusplus +} +#endif diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent00.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent00.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "aod.c" +#include "jni_tools.c" +#include "nsk_tools.c" +#include "agent00.c" diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent01.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent01.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "aod.c" +#include "jni_tools.c" +#include "nsk_tools.c" +#include "agent01.c" diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent02.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent02.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "aod.c" +#include "jni_tools.c" +#include "nsk_tools.c" +#include "agent02.c" diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent03.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/libVirtualMachine07agent03.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "aod.c" +#include "jni_tools.c" +#include "nsk_tools.c" +#include "agent03.c" diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine08/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine08/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine08. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks methods VirtualMachine.loadAgentPath(String agent) and + * VirtualMachine.loadAgentPath(String agent, String options). + * Test checks following cases: + * - it is possible to pass options to agent using loadAgentPath(String agent, String options) + * - it is possible to specify null options (in this case zero-length is passed to the Agent_OnAttach) + * - if Agent_OnAttach returns error code loadAgentPath throws AgentInitializationException and + * AgentInitializationException.returnValue() returns this error code + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07 + * nsk.share.aod.TargetApplicationWaitingAgents + * @run main/othervm/native -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.TargetApplicationWaitingAgents + * -na ${test.nativepath}/VirtualMachine07agent00,${test.nativepath}/VirtualMachine07agent01,${test.nativepath}/VirtualMachine07agent02,${test.nativepath}/VirtualMachine07agent03 + * -testedMethod loadAgentPath + * -arch ${os.family}-${os.simpleArch} + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VM09Target.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VM09Target.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.aod.VirtualMachine.VirtualMachine09; + +import nsk.share.aod.TargetApplicationWaitingAgents; + +public class VM09Target { + + public static void main(String[] args) { + System.loadLibrary("VirtualMachine09agent00"); + System.out.println("Agent library was loaded"); + + new TargetApplicationWaitingAgents().runTargetApplication(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VirtualMachine09.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VirtualMachine09.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine09. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks method VirtualMachine.loadAgentLibrary(String agent). + * Test checks following spec clause: "Agent_OnAttach function is invoked even if the agent library was loaded + * prior to invoking this method". In this test the same agent library first loaded via VM command line + * option 'agentlib:', then it is loaded using method 'System.loadLibrary' and than dynamically attached. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine09.VirtualMachine09 + * nsk.aod.VirtualMachine.VirtualMachine09.VM09Target + * @run main/othervm/native -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine09.VirtualMachine09 + * -jdk ${test.jdk} + * "-javaOpts=-agentlib:VirtualMachine09agent00 -XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.aod.VirtualMachine.VirtualMachine09.VM09Target + * -na VirtualMachine09agent00 + * -testedMethod loadAgentLibrary + */ + +package nsk.aod.VirtualMachine.VirtualMachine09; + +import nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07; +import nsk.share.TestBug; +import nsk.share.aod.*; + +import java.util.*; + +import com.sun.tools.attach.*; + +/* + * Test checks methods VirtualMachine.loadAgentLib and VirtualMachineloadAgentPath. + * + * Test checks following spec clause: "Agent_OnAttach function is invoked even if the agent library was loaded + * prior to invoking this method" + */ +public class VirtualMachine09 extends VirtualMachine07 { + + public VirtualMachine09(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + // check that all required parameters were passed to the test + List agents = argParser.getAgents(); + if (agents.size() != 1) + throw new TestBug("Test requires 1 agent, actually " + agents.size() + " were specified"); + + for (AgentInformation agent : agents) { + if (agent.jarAgent) + throw new TestBug("Non native agent was specified"); + } + + VirtualMachine vm = VirtualMachine.attach(targetVMId); + + try { + AgentInformation agent; + agent = agents.get(0); + loadAgent(vm, agent.pathToAgent, agent.agentOptions); + } finally { + vm.detach(); + } + } + + public static void main(String[] args) { + new VirtualMachine09(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/agent00.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/agent00.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Test checks following spec clause: "Agent_OnAttach function is invoked even if the agent library was loaded + * prior to invoking this method" + * + * This agent is loaded as static agent via 'agentlib:' VM option and also dynamically attached, so this agent + * has both Agent_OnLoad and Agent_OnAttach. + */ + +JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *optionsString, void *reserved) { + // can't use NSK_DISPLAY since needed for nsk_ functions initialization isn't done here + printf("Agent_OnLoad: agent is loaded\n"); + fflush(stdout); + return JNI_OK; +} + +JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved) { + JNIEnv* jni = NULL; + Options* options = NULL; + const char* agentName; + + if (!NSK_VERIFY((options = (Options*) nsk_aod_createOptions(optionsString)) != NULL)) + return JNI_ERR; + + agentName = nsk_aod_getOptionValue(options, NSK_AOD_AGENT_NAME_OPTION); + + if ((jni = (JNIEnv*) nsk_aod_createJNIEnv(vm)) == NULL) + return JNI_ERR; + + NSK_DISPLAY1("%s: initialization was done\n", agentName); + + if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, agentName))) + return JNI_ERR; + + nsk_aod_agentFinished(jni, agentName, 1); + + return JNI_OK; +} + +#ifdef __cplusplus +} +#endif diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/libVirtualMachine09agent00.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/libVirtualMachine09agent00.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "aod.c" +#include "jni_tools.c" +#include "nsk_tools.c" +#include "agent00.c" diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine10/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine10/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachine/VirtualMachine10. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This test checks method VirtualMachine.loadAgentPath(String agent). + * Test checks following spec clause: "Agent_OnAttach function is invoked even if the agent library was loaded + * prior to invoking this method". In this test the same agent library first loaded via VM command line + * option 'agentlib:', then it is loaded using method 'System.loadLibrary' and than dynamically attached. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachine.VirtualMachine09.VirtualMachine09 + * nsk.aod.VirtualMachine.VirtualMachine09.VM09Target + * @run main/othervm/native -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachine.VirtualMachine09.VirtualMachine09 + * -jdk ${test.jdk} + * "-javaOpts=-agentlib:VirtualMachine09agent00 -XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.aod.VirtualMachine.VirtualMachine09.VM09Target + * -na ${test.nativepath}/VirtualMachine09agent00 + * -testedMethod loadAgentPath + * -arch ${os.family}-${os.simpleArch} + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01/VirtualMachineDescriptor01.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01/VirtualMachineDescriptor01.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01. + * VM Testbase keywords: [feature_282, jdk] + * VM Testbase readme: + * Description : + * Test checks work of Attach API (com.sun.tools.attach). + * Test is based on the nsk.share.aod framework. + * This is sanity test for class VirtualMachineDescriptor. + * Test checks that its methods toString(), displayName(), id(), provider() return + * non-null values and also test checks semantics of the method VirtualMachineDescriptor.equals(Object obj). + * Tested VirtualMachineDescriptors are obtained using VirtualMachine.list() + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.aod.VirtualMachineDescriptor.VirtualMachineDescriptor01.VirtualMachineDescriptor01 + * nsk.share.aod.DummyTargetApplication + * @run main/othervm -XX:+UsePerfData PropertyResolvingWrapper + * nsk.aod.VirtualMachineDescriptor.VirtualMachineDescriptor01.VirtualMachineDescriptor01 + * -jdk ${test.jdk} + * "-javaOpts=-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -target nsk.share.aod.DummyTargetApplication + */ + +package nsk.aod.VirtualMachineDescriptor.VirtualMachineDescriptor01; + +import com.sun.tools.attach.*; +import com.sun.tools.attach.spi.AttachProvider; +import nsk.share.aod.*; +import nsk.share.test.TestUtils; + +/* + * Basic sanity checks for class com.sun.tools.attach.VirtualMachineDescriptor + */ +public class VirtualMachineDescriptor01 extends AODTestRunner { + + public VirtualMachineDescriptor01(String[] args) { + super(args); + } + + public void doTestActions(String targetVMId) throws Throwable { + String currentVMId = getCurrentVMId(); + + VirtualMachineDescriptor currentVMDesc = null; + VirtualMachineDescriptor targetVMDesc = null; + + for (VirtualMachineDescriptor vmDescriptor : VirtualMachine.list()) { + log.display("VirtualMachineDescriptor: " + vmDescriptor); + log.display("VirtualMachineDescriptor.displayName(): " + vmDescriptor.displayName()); + log.display("VirtualMachineDescriptor.id(): " + vmDescriptor.id()); + log.display("VirtualMachineDescriptor.provider(): " + vmDescriptor.provider()); + + TestUtils.assertNotNull(vmDescriptor.toString(), "VirtualMachineDescriptor.toString() returns null"); + TestUtils.assertNotNull(vmDescriptor.displayName(), "VirtualMachineDescriptor.displayName() returns null"); + TestUtils.assertNotNull(vmDescriptor.id(), "VirtualMachineDescriptor.id() returns null"); + TestUtils.assertNotNull(vmDescriptor.provider(), "VirtualMachineDescriptor.provider() returns null"); + + TestUtils.assertTrue(AttachProvider.providers().contains(vmDescriptor.provider()), + "AttachProvider.providers() doesn't contain provider '" + vmDescriptor.provider() + "'"); + + if (vmDescriptor.id().equals(currentVMId)) { + currentVMDesc = vmDescriptor; + } else if (vmDescriptor.id().equals(targetVMId)) { + targetVMDesc = vmDescriptor; + } + } + + TestUtils.assertNotNull(currentVMDesc, "VirtualMachine.list() didn't return descriptor for the current VM"); + TestUtils.assertNotNull(targetVMDesc, "VirtualMachine.list() didn't return descriptor for VM with id '" + targetVMId + "'"); + + TestUtils.assertTrue(!currentVMDesc.equals(targetVMDesc), + "VirtualMachineDescriptor.equals() returns 'true' for '" + currentVMDesc + "' and '" + targetVMDesc + "'"); + TestUtils.assertTrue(currentVMDesc.hashCode() != targetVMDesc.hashCode(), + "VirtualMachineDescriptor.hashCode() returns the same value (" + currentVMDesc.hashCode() + ")" + " for '" + + currentVMDesc + "' and '" + targetVMDesc + "'"); + + VirtualMachine targetVM = VirtualMachine.attach(targetVMDesc); + + try { + // create another VirtualMachineDescriptor for target VM + VirtualMachineDescriptor targetVMDesc2 = new VirtualMachineDescriptor(targetVM.provider(), targetVM.id()); + + TestUtils.assertEquals(targetVMDesc, targetVMDesc2, + "VirtualMachineDescriptor.equals() returns 'false' for '" + targetVMDesc + "' and '" + targetVMDesc2 + "'"); + + TestUtils.assertEquals(targetVMDesc.hashCode(), targetVMDesc2.hashCode(), + "VirtualMachineDescriptor.hashCode() returns different values " + "(" + targetVMDesc.hashCode() + " and " + targetVMDesc2.hashCode() + ")" + + " for '" + targetVMDesc + "' and '" + targetVMDesc2 + "'"); + } finally { + targetVM.detach(); + } + } + + public static void main(String[] args) { + new VirtualMachineDescriptor01(args).runTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.GetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ArrayReference.GetValues. + * + * See getvalues001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class getvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ArrayReference.GetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "getvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ArrayReference.GetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ArrayReference.GetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the static field in the tested class with the tested object value + static final String ARRAY_FIELD_NAME = getvalues001a.ARRAY_FIELD_NAME; + static final int ARRAY_LENGTH = getvalues001a.ARRAY_LENGTH; + + // first index and number of array components to get + static final int ARRAY_FIRST_INDEX = 4; + static final int ARRAY_ITEMS_COUNT = 10; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new getvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for arrayID value from static field + log.display("Getting arrayID value from static field: " + + ARRAY_FIELD_NAME); + long arrayID = queryObjectID(classID, + ARRAY_FIELD_NAME, JDWP.Tag.ARRAY); + log.display(" got arrayID: " + arrayID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(arrayID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified objectID. + */ + void testCommand(long arrayID) { + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" arrayID: " + arrayID); + command.addObjectID(arrayID); + log.display(" firstIndex: " + ARRAY_FIRST_INDEX); + command.addInt(ARRAY_FIRST_INDEX); + log.display(" length: " + ARRAY_ITEMS_COUNT); + command.addInt(ARRAY_ITEMS_COUNT); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract values tag + byte tag = (byte)0; + try { + tag = reply.getByte(); + log.display(" tag: " + tag); + + } catch (BoundException e) { + log.complain("Unable to extract values tag from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check if number of values are as expected + if (tag != JDWP.Tag.INT) { + log.complain("Unexpected values tag received:" + tag + + " (expected: " + JDWP.Tag.INT + ")"); + success = false; + } + + // extract number of values + int values = 0; + try { + values = reply.getInt(); + log.display(" values: " + values); + + } catch (BoundException e) { + log.complain("Unable to extract number of values from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check if number of values are as expected + if (values < 0) { + log.complain("Negative number of values received:" + values + + " (expected: " + ARRAY_ITEMS_COUNT + ")"); + success = false; + } else if (values != ARRAY_ITEMS_COUNT) { + log.complain("Unexpected number of values received:" + values + + " (expected: " + ARRAY_ITEMS_COUNT + ")"); + success = false; + } + + // extract and check each value + for (int i = 0; i < values; i++ ) { + int index = i + ARRAY_FIRST_INDEX; + log.display(" value #" + i + " (index: " + index + ")"); + + // extract value + JDWP.UntaggedValue value = null; + try { + value = reply.getUntaggedValue(JDWP.Tag.INT); + log.display(" untagged_value: " + value); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " value from reply packet:\n\t" + + e.getMessage()); + success = false; + break; + } + + // check that extracted value is as expected + int intValue = ((Integer)value.getValue()).intValue(); + if (intValue != index * 10) { + log.complain("Unexpected value for " + index + " component received: " + + intValue + " (expected: " + (index * 10) + ")"); + success = false; + } + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ArrayReference/GetValues/getvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ArrayReference + * command: GetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the returned values of requested array components are equal + * to the expected ones. Tested array contains primitive values. + * Test consists of two compoments: + * debugger: getvalues001 + * debuggee: getvalues001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains from debuggee classID for the tested class and + * arrayID as the value of the class static field. Checked array in + * debuggee is filled with the regular integer values. + * Then, debugger creates command packet for GetValues command with the + * found arrayID and start index and number of components as arguments, + * writes packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts values of the array components. Also test checks + * that extracted values are equal to the expected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ArrayReference.GetValues.getvalues001 + * nsk.jdwp.ArrayReference.GetValues.getvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ArrayReference.GetValues.getvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.GetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class getvalues001a { + + public static final String ARRAY_FIELD_NAME = "array"; + public static final int ARRAY_LENGTH = 16; + + public static void main(String args[]) { + getvalues001a _getvalues001a = new getvalues001a(); + System.exit(getvalues001.JCK_STATUS_BASE + _getvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating and fille tested array"); + TestedClass.setArrayValues(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + getvalues001.READY); + pipe.println(getvalues001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + getvalues001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(getvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + getvalues001.QUIT + ")"); + log.display("Debugee FAILED"); + return getvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return getvalues001.PASSED; + } + + // tested class with own static fields values + public static class TestedClass { + + // static field with tested array + public static int array[] = null; + + public static void setArrayValues() { + array = new int[ARRAY_LENGTH]; + for (int i = 0; i < ARRAY_LENGTH; i++) { + array[i] = i * 10; + } + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.GetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ArrayReference.GetValues. + * + * See getvalues002.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class getvalues002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ArrayReference.GetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "getvalues002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ArrayReference.GetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ArrayReference.GetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the static field in the tested class with the tested object value + static final String ARRAY_FIELD_NAME = getvalues002a.ARRAY_FIELD_NAME; + static final int ARRAY_LENGTH = getvalues002a.ARRAY_LENGTH; + + // names of the statc fields with object values + static final int FIELDS_COUNT = getvalues002a.FIELDS_COUNT; + static final String FIELD_NAMES[] = { + "nullObject", + "baseObject", + "derivedObject", + "stringObject", + "primitiveArrayObject", + "objectArrayObject", + "threadObject", + "threadGroupObject", + "classObject", + "classLoaderObject", + }; + static final byte FIELD_TAGS[] = { + JDWP.Tag.OBJECT, // nullObject + JDWP.Tag.OBJECT, // baseobject + JDWP.Tag.OBJECT, // derivedObject + JDWP.Tag.STRING, // stringObject + JDWP.Tag.ARRAY, // primitiveArrayObject + JDWP.Tag.ARRAY, // objectArrayObject + JDWP.Tag.THREAD, // threadObject + JDWP.Tag.THREAD_GROUP, // threadGroupObject + JDWP.Tag.CLASS_OBJECT, // classObject + JDWP.Tag.CLASS_LOADER // classLoaderObject + }; + + // first index and number of array components to get + static final int ARRAY_FIRST_INDEX = getvalues002a.ARRAY_FIRST_INDEX; + static final int ARRAY_ITEMS_COUNT = FIELDS_COUNT; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new getvalues002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debugee for fieldIDs of the class static fields + log.display("Getting fieldIDs for static fields of the class"); + long fieldIDs[] = queryClassFieldIDs(classID); + log.display(" got fields: " + fieldIDs.length); + + // query debugee for object values of the fields + log.display("Getting objectID values of the static fields"); + long objectIDs[] = queryClassFieldValues(classID, fieldIDs); + log.display(" got objectIDs: " + objectIDs.length); + + // query debuggee for arrayID value from static field + log.display("Getting arrayID value from static field: " + + ARRAY_FIELD_NAME); + long arrayID = queryObjectID(classID, + ARRAY_FIELD_NAME, JDWP.Tag.ARRAY); + log.display(" got arrayID: " + arrayID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(arrayID, objectIDs); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debugee for fieldID's of the class static fields. + */ + long[] queryClassFieldIDs(long classID) { + + long[] fieldIDs = new long[FIELDS_COUNT]; + for (int i = 0; i < FIELDS_COUNT; i++) { + fieldIDs[i] = 0; + } + + // compose ReferenceType.Fields command packet + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(classID); + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract fieldIDs from the reply packet + try { + reply.resetPosition(); + + int declared = reply.getInt(); + + for (int i = 0; i < declared; i++ ) { + long fieldID = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + for (int j = 0; j < FIELDS_COUNT; j++) { + if (FIELD_NAMES[j].equals(name)) { + fieldIDs[j] = fieldID; + } + } + } + + for (int i = 0; i < FIELDS_COUNT; i++) { + if (fieldIDs[i] == 0) { + log.complain("Not found fieldID for static field: " + FIELD_NAMES[i]); + throw new Failure("Error occured while getting static fieldIDs for classID: " + + classID); + } + } + + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.Fields command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fieldIDs for classID: " + classID); + } + + return fieldIDs; + } + + /** + * Query debugee for objectID values of the class fields. + */ + long[] queryClassFieldValues(long classID, long fieldIDs[]) { + String error = "Error occured while getting object values for static fields of classID: " + + classID; + + // compose ReferenceType.Fields command packet + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.GetValues); + command.addReferenceTypeID(classID); + command.addInt(FIELDS_COUNT); + for (int i = 0; i < FIELDS_COUNT; i++) { + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract values from the reply packet + try { + reply.resetPosition(); + + int valuesCount = reply.getInt(); + if (valuesCount != FIELDS_COUNT) { + log.complain("Unexpected number of values for static fields: " + valuesCount + + " (expected: " + FIELDS_COUNT + ")"); + throw new Failure(error); + } + + long objectIDs[] = new long[valuesCount]; + for (int i = 0; i < valuesCount; i++ ) { + JDWP.Value value = reply.getValue(); + byte tag = value.getTag(); + if (tag != FIELD_TAGS[i]) { + log.complain("Unexpected tag of oblectID value for static field " + + FIELD_NAMES[i] + ": " + tag + + " (expected: " + FIELD_TAGS[i] + ")"); + throw new Failure(error); + } + long objectID = ((Long)value.getValue()).longValue(); + objectIDs[i] = objectID; + } + return objectIDs; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.GetValues command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fields values for classID: " + classID); + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified objectID. + */ + void testCommand(long arrayID, long objectIDs[]) { + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" arrayID: " + arrayID); + command.addObjectID(arrayID); + log.display(" firstIndex: " + ARRAY_FIRST_INDEX); + command.addInt(ARRAY_FIRST_INDEX); + log.display(" length: " + ARRAY_ITEMS_COUNT); + command.addInt(ARRAY_ITEMS_COUNT); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract values tag + byte tag = (byte)0; + try { + tag = reply.getByte(); + log.display(" tag: " + tag); + + } catch (BoundException e) { + log.complain("Unable to extract values tag from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check if number of values are as expected + if (tag != JDWP.Tag.OBJECT) { + log.complain("Unexpected values tag received:" + tag + + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // extract number of values + int values = 0; + try { + values = reply.getInt(); + log.display(" values: " + values); + + } catch (BoundException e) { + log.complain("Unable to extract number of values from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check if number of values are as expected + if (values < 0) { + log.complain("Negative number of values received:" + values + + " (expected: " + ARRAY_ITEMS_COUNT + ")"); + success = false; + } else if (values != ARRAY_ITEMS_COUNT) { + log.complain("Unexpected number of values received:" + values + + " (expected: " + ARRAY_ITEMS_COUNT + ")"); + success = false; + } + + // extract and check each value + for (int i = 0; i < values; i++ ) { + int index = i + ARRAY_FIRST_INDEX; + log.display(" value #" + i + " (index: " + index + ")"); + + // extract value + JDWP.Value value = null; + try { + value = reply.getValue(); + log.display(" value: " + value); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " value from reply packet:\n\t" + + e.getMessage()); + success = false; + break; + } + + // check that value's tag is as expected + byte valueTag = value.getTag(); + if (valueTag != FIELD_TAGS[i]) { + log.complain("Unexpected value tag for " + index + " component (" + + FIELD_NAMES[i] + ") received: " + valueTag + + " (expected: " + FIELD_TAGS[i] + ")"); + success = false; + } + + // check that value's objectID is as expected + long objectID = ((Long)value.getValue()).longValue(); + if (objectID != objectIDs[i]) { + log.complain("Unexpected objectID for " + index + " component (" + + FIELD_NAMES[i] + ") received: " + objectID + + " (expected: " + objectIDs[i] + ")"); + success = false; + } + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ArrayReference/GetValues/getvalues002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ArrayReference + * command: GetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the returned values of requested array components are equal + * to the expected ones. Tested array contains object values + * of several kinds (objects, strings, arrays, threads, etc.) + * Test consists of two compoments: + * debugger: getvalues002 + * debuggee: getvalues002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains from debuggee classID for the tested class and + * arrayID as the value of the class static field. Also debugger obtains + * object values from static fileds. These values are the same as components + * of the tested array. + * Then, debugger creates command packet for GetValues command with the + * found arrayID and start index and number of components as arguments, + * writes packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts values of the array components. Also test checks + * that extracted object values are equal to the expected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ArrayReference.GetValues.getvalues002 + * nsk.jdwp.ArrayReference.GetValues.getvalues002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ArrayReference.GetValues.getvalues002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.GetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class getvalues002a { + + public static final String ARRAY_FIELD_NAME = "array"; + public static final int FIELDS_COUNT = 10; + public static final int ARRAY_FIRST_INDEX = 4; + public static final int ARRAY_LENGTH = ARRAY_FIRST_INDEX + FIELDS_COUNT + 5; + + public static void main(String args[]) { + getvalues002a _getvalues002a = new getvalues002a(); + System.exit(getvalues002.JCK_STATUS_BASE + _getvalues002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating and fille tested array"); + TestedClass.setArrayValues(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + getvalues002.READY); + pipe.println(getvalues002.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + getvalues002.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(getvalues002.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + getvalues002.QUIT + ")"); + log.display("Debugee FAILED"); + return getvalues002.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return getvalues002.PASSED; + } + + // tested class with own static fields values + public static class TestedClass { + + // static field with tested array + public static Object array[] = null; + + // static fields with object values + public static Object nullObject = null; + public static Object baseObject = new Object(); + public static TestedClass derivedObject = new TestedClass(); + public static String stringObject = new String("string"); + public static int[] primitiveArrayObject = new int[10]; + public static Object[] objectArrayObject = new Object[10]; + public static Thread threadObject = Thread.currentThread(); + public static ThreadGroup threadGroupObject = threadObject.getThreadGroup(); + public static Class classObject = derivedObject.getClass(); + public static ClassLoader classLoaderObject = classObject.getClassLoader(); + + public static void setArrayValues() { + array = new Object[ARRAY_LENGTH]; + for (int i = 0; i < ARRAY_LENGTH; i++) { + array[i] = null; + } + + int i = ARRAY_FIRST_INDEX; + array[i + 0] = nullObject; + array[i + 1] = baseObject; + array[i + 2] = derivedObject; + array[i + 3] = stringObject; + array[i + 4] = primitiveArrayObject; + array[i + 5] = objectArrayObject; + array[i + 6] = threadObject; + array[i + 7] = threadGroupObject; + array[i + 8] = classObject; + array[i + 9] = classLoaderObject; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.Length; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ArrayReference.Length. + * + * See length001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class length001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ArrayReference.Length"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "length001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ArrayReference.Length"; + static final int JDWP_COMMAND_ID = JDWP.Command.ArrayReference.Length; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the static field in the tested class with the tested object value + static final String ARRAY_FIELD_NAME = length001a.ARRAY_FIELD_NAME; + static final int ARRAY_LENGTH = length001a.ARRAY_LENGTH; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new length001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for arrayID value from static field + log.display("Getting arrayID value from static field: " + + ARRAY_FIELD_NAME); + long arrayID = queryObjectID(classID, + ARRAY_FIELD_NAME, JDWP.Tag.ARRAY); + log.display(" got arrayID: " + arrayID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(arrayID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified arrayID. + */ + void testCommand(long arrayID) { + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" arrayID: " + arrayID); + command.addObjectID(arrayID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract array length + int arrayLength = 0; + try { + arrayLength = reply.getInt(); + log.display(" arrayLength: " + arrayLength); + + } catch (BoundException e) { + log.complain("Unable to extract arrayLength from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check if arrayLength is as expected + if (arrayLength < 0) { + log.complain("Negative number of arrayLength received:" + arrayLength + + " (expected: " + ARRAY_LENGTH + ")"); + success = false; + } else if (arrayLength != ARRAY_LENGTH) { + log.complain("Unexpected number of values received:" + arrayLength + + " (expected: " + ARRAY_LENGTH + ")"); + success = false; + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ArrayReference/Length/length001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ArrayReference + * command: Length + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the returned array length is equal to the expected one. + * Test consists of two compoments: + * debugger: length001 + * debuggee: length001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains from debuggee classID for the tested class and + * arrayID as the value of the class static field. Checked array in + * debuggee is filled with the regular integer values. + * Then, debugger creates command packet for Length command with the + * found arrayID and start index and number of components as arguments, + * writes packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts array length value. Also test checks that extracted array + * length is equal to the expected one. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ArrayReference.Length.length001 + * nsk.jdwp.ArrayReference.Length.length001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ArrayReference.Length.length001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.Length; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class length001a { + + public static final String ARRAY_FIELD_NAME = "array"; + public static final int ARRAY_LENGTH = 16; + + public static void main(String args[]) { + length001a _length001a = new length001a(); + System.exit(length001.JCK_STATUS_BASE + _length001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating and fille tested array"); + TestedClass.setArrayValues(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + length001.READY); + pipe.println(length001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + length001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(length001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + length001.QUIT + ")"); + log.display("Debugee FAILED"); + return length001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return length001.PASSED; + } + + // tested class with own static fields values + public static class TestedClass { + + // static field with tested array + public static int array[] = null; + + public static void setArrayValues() { + array = new int[ARRAY_LENGTH]; + for (int i = 0; i < ARRAY_LENGTH; i++) { + array[i] = i * 10; + } + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.SetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ArrayReference.SetValues. + * + * See setvalues001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class setvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String RUN = "run"; + static final String DONE = "done"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ArrayReference.SetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "setvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ArrayReference.SetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ArrayReference.SetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the static field in the tested class with the tested object value + static final String ARRAY_FIELD_NAME = setvalues001a.ARRAY_FIELD_NAME; + + // length, first index and number of array components to get + static final int ARRAY_LENGTH = setvalues001a.ARRAY_LENGTH; + static final int ARRAY_FIRST_INDEX = setvalues001a.ARRAY_FIRST_INDEX; + static final int ARRAY_ITEMS_COUNT = setvalues001a.ARRAY_ITEMS_COUNT; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new setvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for arrayID value from static field + log.display("Getting arrayID value from static field: " + + ARRAY_FIELD_NAME); + long arrayID = queryObjectID(classID, + ARRAY_FIELD_NAME, JDWP.Tag.ARRAY); + log.display(" got arrayID: " + arrayID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(arrayID); + + // check confirmation from debuggee that values have been set correctly + log.display("\n>>> Checking that the values have been set correctly \n"); + checkValuesChanged(); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified objectID. + */ + void testCommand(long arrayID) { + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" arrayID: " + arrayID); + command.addObjectID(arrayID); + log.display(" firstIndex: " + ARRAY_FIRST_INDEX); + command.addInt(ARRAY_FIRST_INDEX); + log.display(" values: " + ARRAY_ITEMS_COUNT); + command.addInt(ARRAY_ITEMS_COUNT); + // add new int values for array components + for (int i = ARRAY_FIRST_INDEX; i < ARRAY_FIRST_INDEX + ARRAY_ITEMS_COUNT; i++) { + int intValue = i * 100 + 1; + JDWP.UntaggedValue value = new JDWP.UntaggedValue(new Integer(intValue)); + log.display(" untagged_value: " + value); + command.addUntaggedValue(value, JDWP.Tag.INT); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no reply data to extract + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + + /** + * Check confirmation from debuggee that values are changed correctly. + */ + void checkValuesChanged() { + // send debugee signal RUN + log.display("Sending signal to debugee: " + RUN); + pipe.println(RUN); + + // wait for DONE signal from debugee + log.display("Waiting for signal from debugee: " + DONE); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + // check received signal + if (signal == null) { + throw new TestBug(" signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } else if (signal.equals(DONE)) { + log.display("All array values have been correctly set into debuggee VM"); + } else if (signal.equals(ERROR)) { + log.complain("Not all array values have been correctly set into debuggee VM"); + success = false; + } else { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ArrayReference/SetValues/setvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ArrayReference + * command: SetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the new set values of array components are equal to the + * expected ones. + * Test consists of two compoments: + * debugger: setvalues001 + * debuggee: setvalues001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains from debuggee classID for the tested class and + * arrayID as the value of the class static field. Checked array in + * debuggee is filled with the initial integer values. + * Then, debugger creates command packet for SetValues command with the + * found arrayID, start index and number of components as arguments, + * and new integer values, writes packet to the transport channel + * and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and ensures there is no data in the packet. Also test send signal + * to debuggee to check new array values. If new values are set + * correctly debuggee replies with signal DONE. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ArrayReference.SetValues.setvalues001 + * nsk.jdwp.ArrayReference.SetValues.setvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ArrayReference.SetValues.setvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayReference.SetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class setvalues001a { + + // name of the static field with the tested array object + public static final String ARRAY_FIELD_NAME = "array"; + + // length, first index and number of array components to get + public static final int ARRAY_LENGTH = 16; + public static final int ARRAY_FIRST_INDEX = 4; + public static final int ARRAY_ITEMS_COUNT = 10; + + private static ArgumentHandler argumentHandler = null; + private static Log log = null; + + public static void main(String args[]) { + setvalues001a _setvalues001a = new setvalues001a(); + System.exit(setvalues001.JCK_STATUS_BASE + _setvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating and initializing tested array"); + TestedClass.initArrayValues(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + setvalues001.READY); + pipe.println(setvalues001.READY); + + // wait for signal RUN from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.RUN); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + // check received signal + if (signal == null || !signal.equals(setvalues001.RUN)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.RUN + ")"); + log.display("Debugee FAILED"); + return setvalues001.FAILED; + } + + // check assigned values + log.display("Checking new array values"); + if (TestedClass.checkArrayValues()) { + log.display("Sending signal to debugger: " + setvalues001.DONE); + pipe.println(setvalues001.DONE); + } else { + log.display("Sending signal to debugger: " + setvalues001.ERROR); + pipe.println(setvalues001.ERROR); + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.QUIT); + signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(setvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.QUIT + ")"); + log.display("Debugee FAILED"); + return setvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return setvalues001.PASSED; + } + + // tested class with own static fields values + public static class TestedClass { + + // static field with tested array + public static int array[] = null; + + public static void initArrayValues() { + array = new int[ARRAY_LENGTH]; + for (int i = 0; i < ARRAY_LENGTH; i++) { + array[i] = i * 10; + } + } + + public static boolean checkArrayValues() { + if (array == null) { + log.complain("Checked array == null after setting values: " + array); + return false; + } + + boolean success = true; + if (array.length != ARRAY_LENGTH) { + log.complain("Unexpected array length after setting values: " + + array.length + " (expected: " + ARRAY_LENGTH + ")"); + success = false; + } + + for (int i = 0; i < array.length; i++) { + int initial = i * 10; + int changed = i * 100 + 1; + if (i < ARRAY_FIRST_INDEX || i >= ARRAY_FIRST_INDEX + ARRAY_ITEMS_COUNT) { + log.display(" " + i + " (not changed): " + initial + " -> " + array[i]); + if (array[i] != initial) { + log.complain("Changed value of " + i + " component which is out of changed region: " + + array[i] + "(initial: " + initial + ")"); + success = false; + } + } else { + log.display(" " + i + " (changed): " + initial + " -> " + array[i]); + if (array[i] != changed) { + if (array[i] == initial) { + log.complain("Value of " + i + " component not changed: " + + array[i] + "(expected: " + changed + ")"); + success = false; + } else { + log.complain("Value of " + i + " component changed incorrectly: " + + array[i] + "(expected: " + changed + ")"); + success = false; + } + } + } + } + + return success; + } + + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayType.NewInstance; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ArrayType.NewInstance. + * + * See newinstance001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class newinstance001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ArrayType.NewInstance"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "newinstance001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ArrayType.NewInstance"; + static final int JDWP_COMMAND_ID = JDWP.Command.ArrayType.NewInstance; + + // tested array type signature constant + static final String TESTED_ARRAY_SIGNATURE = "[I"; + + // tested array type size constant + static final int TESTED_ARRAY_SIZE = 100; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new newinstance001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting arrayTypeID by signature:\n" + + " " + TESTED_ARRAY_SIGNATURE); + long typeID = debugee.getReferenceTypeID(TESTED_ARRAY_SIGNATURE); + log.display(" got TypeID: " + typeID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(typeID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long typeID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" arrayTypeID: " + typeID); + command.addReferenceTypeID(typeID); + log.display(" length: " + TESTED_ARRAY_SIZE); + command.addInt(TESTED_ARRAY_SIZE); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check number of nested classes + JDWP.Value newArray = null; + try { + newArray = reply.getValue(); + log.display(" newArray: " + newArray); + + byte tag = newArray.getTag(); + if (tag != JDWP.Tag.ARRAY) { + log.complain("Unexpected tag of new array value in the reply packet:" + + tag + " (expected: " + JDWP.Tag.ARRAY + ")"); + success = false; + } + + long objectID = 0; + try { + objectID = ((Long)newArray.getValue()).longValue(); + } catch (ClassCastException e) { + throw new TestBug("Caught ClassCastException vhile extracting objectID from tagged value: " + + newArray); + } + + if (objectID == 0) { + log.complain("Null objectID returned for new array value in the reply packet"); + success = false; + } + + } catch (BoundException e) { + log.complain("Unable to extract newArray value from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ArrayType/NewInstance/newinstance001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ArrayType + * command: NewInstance + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: newinstance001 + * debuggee: newinstance001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains arrayTypeIDs for the tested class from debugee. + * Then, debugger creates command packet for ArrayType.NewInstance command + * with the found arrayTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts tagged objectID value of the new created array. Also test + * checks that the tag of the extracted value is ARRAY_ID and objectID is + * not null. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ArrayType.NewInstance.newinstance001 + * nsk.jdwp.ArrayType.NewInstance.newinstance001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ArrayType.NewInstance.newinstance001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ArrayType.NewInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class newinstance001a { + + public static void main(String args[]) { + newinstance001a _newinstance001a = new newinstance001a(); + System.exit(newinstance001.JCK_STATUS_BASE + _newinstance001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested array type is loaded + log.display("Creating array of integer"); + int foo[] = new int[10]; + + // send debugger signal READY + log.display("Sending signal to debugger: " + newinstance001.READY); + pipe.println(newinstance001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + newinstance001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(newinstance001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + newinstance001.QUIT + ")"); + log.display("Debugee FAILED"); + return newinstance001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return newinstance001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassLoaderReference.VisibleClasses; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ClassLoaderReference.VisibleClasses. + * + * See visibclasses001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class visibclasses001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ClassLoaderReference.VisibleClasses"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "visibclasses001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ClassLoaderReference.VisibleClasses"; + static final int JDWP_COMMAND_ID = JDWP.Command.ClassLoaderReference.VisibleClasses; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new visibclasses001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debugee for TypeIDs of classes been nested + log.display("Getting classLoaderID for tested classes"); + long classLoaderID = queryClassLoaderID(classID); + log.display(" got classLoaderID: " + classLoaderID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classLoaderID, classID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debugee for classLoaderID for specified classID. + */ + long queryClassLoaderID(long classID) { + CommandPacket command = + new CommandPacket(JDWP.Command.ReferenceType.ClassLoader); + command.addReferenceTypeID(classID); + ReplyPacket reply = debugee.receiveReplyFor(command); + + try { + reply.resetPosition(); + + long classLoaderID = reply.getObjectID(); + return classLoaderID; + } catch (BoundException e) { + throw new Failure("Unable to parse reply packet for ReferenceType.ClassLoader:\n\t" + + e); + } + } + + /** + * Perform testing JDWP command for specified classLoaderID. + */ + void testCommand(long classLoaderID, long expectedClassID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + log.display(" classLoaderID: " + classLoaderID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(classLoaderID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check number of nested classes + int classes = 0; + try { + classes = reply.getInt(); + log.display(" classes: " + classes); + + } catch (BoundException e) { + log.complain("Unable to extract number of nested classes from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + if (classes < 0) { + log.complain("Negative number of classes in the reply packet:" + classes); + success = false; + } else if (classes == 0) { + log.complain("Zero number of classes in the reply packet:" + classes); + success = false; + } + + boolean found = false; + // extract and check TypeID for each received class + for (int i = 0; i < classes; i++ ) { + log.display(" class #" + i); + + // extract TypeTag byte + byte refTypeTag = (byte)0; + String refTypeTagName = null; + try { + refTypeTag = reply.getByte(); + String tag; + switch (refTypeTag) { + case JDWP.TypeTag.CLASS: + refTypeTagName = "CLASS"; + break; + case JDWP.TypeTag.INTERFACE: + refTypeTagName = "INTERFACE"; + break; + case JDWP.TypeTag.ARRAY: + refTypeTagName = "ARRAY"; + break; + default: + refTypeTagName = "UNKNOWN"; + break; + } + log.display(" refTypeTag: " + refTypeTag + "=" + refTypeTagName); + } catch (BoundException e) { + log.complain("Unable to extract refTypetag of " + i + + " class from reply packet:\n\t" + + e.getMessage()); + success = false; + break; + } + + // extract and check TypeID + long typeID = 0; + try { + typeID = reply.getReferenceTypeID(); + log.display(" typeID: " + typeID); + + } catch (BoundException e) { + log.complain("Unable to extract TypeID of " + i + + " nested class from reply packet:\n\t" + + e.getMessage()); + success = false; + break; + } + + if (typeID == expectedClassID) { + log.display("Found expected classID: " + expectedClassID); + found = true; + if (refTypeTag != JDWP.TypeTag.CLASS) { + log.complain("unexpected refTypeTag returned for checked class: " + + refTypeTag + "=" + refTypeTagName + + " (expected: " + JDWP.TypeTag.CLASS + "=CLASS)"); + success = false; + } + } + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.offsetString()); + success = false; + } + + if (!found) { + log.complain("Expected classID not found in the list of visible classes: " + expectedClassID); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ClassLoaderReference + * command: VisibleClasses + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * list of classes returned for classObjectID contains at least + * one expected classID. + * Test consists of two compoments: + * debugger: visibclasses001 + * debuggee: visibclasses001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID for the tested class and its + * classLoaderID from debugee. + * Then, debugger creates command packet for VisibleClasses command + * with the found classObjectID as an argument, writes packet to the + * transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts list of typeIDs of the visible classes. Also test checks + * that this list includes expected classID of the original class. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ClassLoaderReference.VisibleClasses.visibclasses001 + * nsk.jdwp.ClassLoaderReference.VisibleClasses.visibclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ClassLoaderReference.VisibleClasses.visibclasses001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassLoaderReference.VisibleClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class visibclasses001a { + + public static void main(String args[]) { + visibclasses001a _visibclasses001a = new visibclasses001a(); + System.exit(visibclasses001.JCK_STATUS_BASE + _visibclasses001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + visibclasses001.READY); + pipe.println(visibclasses001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + visibclasses001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(visibclasses001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + visibclasses001.QUIT + ")"); + log.display("Debugee FAILED"); + return visibclasses001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return visibclasses001.PASSED; + } + + // tested class with nested classes + public static class TestedClass { + int foo = 0; + public TestedClass() { + foo = 100; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassObjectReference.ReflectedType; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class reflectype001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ClassObjectReference.ReflectedType"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "reflectype001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ClassObjectReference.ReflectedType"; + static final int JDWP_COMMAND_ID = JDWP.Command.ClassObjectReference.ReflectedType; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new reflectype001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + + // get referenceTypeID for debugee class + + long originalTypeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // get classObjectID for originalTypeID + + long classObjectID = 0; + { + log.display("Getting classObjectID for referenceTypeID: " + originalTypeID); + + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.ClassObject); + command.addReferenceTypeID(originalTypeID); + + ReplyPacket reply = debugee.receiveReplyFor(command); + + classObjectID = reply.getObjectID(); + log.display("Found classObjectID: " + classObjectID); + + } + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with classObjectID: " + classObjectID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(classObjectID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + byte refTypeTag = reply.getByte(); + log.display(" refTypeTag: " + classObjectID); + + long typeID = reply.getReferenceTypeID(); + log.display(" typeID: " + typeID); + + if (refTypeTag != JDWP.TypeTag.CLASS) { + log.complain("No JDWP.TypeTag.CLASS tag returned for class object: " + refTypeTag); + success = false; + } + + if (typeID != originalTypeID) { + log.complain("Returned typeID does not equal to original referenceTypeID: " + originalTypeID); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while connecting to debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ClassObjectReference + * command: RefelectedType + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test check if + * received referenceTypeID for class object is equal to + * the original one. + * Test consists of two compoments: + * debugger: reflectype001 + * debuggee: reflectype001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class and then + * classObjectID, which will be used to test JDWP command. + * Then, debugger creates command packet for RefelectedType command with the + * found classObjectID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts referenceTypeID. Debugger tests also that obtained + * referenceTypeID has the proper tag and is equal to the original one. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * Fixed misprint in package name according to test bug: + * 4782469 TEST_RFE: incorrect package name in some JPDA tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ClassObjectReference.ReflectedType.reflectype001 + * nsk.jdwp.ClassObjectReference.ReflectedType.reflectype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ClassObjectReference.ReflectedType.reflectype001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassObjectReference.ReflectedType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class reflectype001a { + + public static void main(String args[]) { + reflectype001a _reflectype001a = new reflectype001a(); + System.exit(reflectype001.JCK_STATUS_BASE + _reflectype001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return reflectype001.PASSED; + } + + static public class TestedClass { + int foo = 0; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassType.InvokeMethod; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ClassType.InvokeMethod. + * + * See invokemeth001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class invokemeth001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names + static final String PACKAGE_NAME = "nsk.jdwp.ClassType.InvokeMethod"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "invokemeth001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command + static final String JDWP_COMMAND_NAME = "ClassType.InvokeMethod"; + static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.InvokeMethod; + + // tested class name and signature + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // field and method names + static final String RESULT_FIELD_NAME = "result"; + static final String TESTED_METHOD_NAME = "testedMethod"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE_NUMBER = invokemeth001a.BREAKPOINT_LINE_NUMBER; + + // data for invoked method + static final int ARGUMENTS_COUNT = 1; + static final int INITIAL_VALUE = invokemeth001a.INITIAL_VALUE; + static final int ARGUMENT_VALUE = invokemeth001a.FINAL_VALUE; + static final int RETURN_VALUE = INITIAL_VALUE; + static final int INVOKE_OPTIONS = 0; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // data obtained from debuggee + long classID = 0; + long threadID = 0; + long methodID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new invokemeth001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); // minutes + timeout = waitTime * 60 * 1000; // milliseconds + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee VM"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debuggee launched"); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for VM_INIT event + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee for testing and obtain required data + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>> Testing JDWP command \n"); + testCommand(); + + // check command results + if (success) { + log.display("\n>>> Checking result of tested command \n"); + checkResult(); + } + + // finish debuggee + log.display("\n>> Finishing debuggee \n"); + + // resume debuggee after testing command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for VM_DEATH event + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + log.display(" ... VM_DEATH event received"); + dead = true; + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + log.display("\n>>> Finishing test \n"); + + // disconnect debugee and wait for its exit + if (debugee != null) { + quitDebugee(); + } + } + + // check result + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + out.println("TEST PASSED"); + return PASSED; + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded on debuggee startup and obtain its classID + log.display("Waiting for class loaded:\n\t" + TESTED_CLASS_NAME); + classID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... class loaded with classID: " + classID); + log.display(""); + + // query debuggee for tested methodID + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + methodID); + log.display(""); + + // set breakpoint and wait for debugee reached it + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_NUMBER); + threadID = debugee.waitForBreakpointReached(classID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE_NUMBER, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + threadID); + log.display("Tested thread is suspended by breakpoint event"); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" classID: " + classID); + command.addReferenceTypeID(classID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + log.display(" arguments: " + ARGUMENTS_COUNT); + command.addInt(ARGUMENTS_COUNT); + for (int i = 0; i < ARGUMENTS_COUNT; i++) { + JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); + log.display(" arg: " + value); + command.addValue(value); + } + log.display(" options: " + INVOKE_OPTIONS); + command.addInt(INVOKE_OPTIONS); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet for tested command:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // extract return value + JDWP.Value returnValue = null; + try { + returnValue = reply.getValue(); + log.display(" returnValue: " + returnValue); + } catch (BoundException e) { + log.complain("Unable to extract returnValues from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract exception tag + JDWP.Value exception = null; + try { + exception = reply.getValue(); + log.display(" exception: " + exception); + } catch (BoundException e) { + log.complain("Unable to extract exception from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... packed data parsed"); + + // check that return value is an integer + if (returnValue.getTag() != JDWP.Tag.INT) { + log.complain("Unexpected tag of returnValue returned: " + returnValue.getTag() + + " (expected: " + JDWP.Tag.INT + ")"); + success = false; + } + + // check that return value is as expected + int intValue = ((Integer)returnValue.getValue()).intValue(); + if (intValue != RETURN_VALUE) { + log.complain("Unexpected value of returnValue returned: " + intValue + + " (expected: " + RETURN_VALUE + ")"); + success = false; + } + + // check that exception value is an object + if (exception.getTag() != JDWP.Tag.OBJECT) { + log.complain("Unexpected tag of exception returned: " + exception.getTag() + + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // check that exception object is null + long exceptionID = ((Long)exception.getValue()).longValue(); + if (exceptionID != 0) { + log.complain("Non-null exception object returned: " + exceptionID + + " (expected: " + 0 + ")"); + success = false; + } + } + + /** + * Check result of the tested JDWP command. + */ + void checkResult() { + // query debuggee for result value from a static field + log.display("Getting result value from static field: " + RESULT_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(classID, RESULT_FIELD_NAME, JDWP.Tag.INT); + int result = ((Integer)value.getValue()).intValue(); + log.display(" ... got result: " + result); + + // check if the result value is changed as expected + if (result != ARGUMENT_VALUE) { + log.complain("Method has not been really invoked: \n\t" + + "variable not changed by the method: " + result + + " (expected: " + ARGUMENT_VALUE + ")"); + success = false; + } else { + log.display("Method has been really invoked: \n\t" + + " variable changed by the method: " + result + + " (expected: " + ARGUMENT_VALUE + ")"); + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ClassType/InvokeMethod/invokemeth001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ClassType + * command: InvokeMethod + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the tested static method is really invoked into debuggee. + * Test consists of two compoments: + * debugger: invokemeth001 + * debuggee: invokemeth001a + * First, debugger uses nsk.share.* support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded, requests methodID + * for tested method, sets breakpoint and wait for breakpoint reached. + * When breakpoint event received the tested thread into debuggee + * is suspended by this event. + * Then, debugger creates command packet for ClassType.InvokeMethod + * command with the found classID, methodID, threadID, and also adds + * one integer argument for the method invocation. Then debugger writes + * packet to the transport channel and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts method's result value and exception objectID. Test checks + * if result value is an expected integer and exception objectID is null. + * Also test gets value of static field, wich should be modified by + * the invoked method, to verify if this method was really invoked + * into debuggee. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ClassType.InvokeMethod.invokemeth001 + * nsk.jdwp.ClassType.InvokeMethod.invokemeth001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ClassType.InvokeMethod.invokemeth001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.ClassType.InvokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class invokemeth001a { + + // name of the tested thread + public static final String THREAD_NAME = "testedThread"; + + // line nunber for breakpoint + public static final int BREAKPOINT_LINE_NUMBER = 86; + + // initial and final value of variable changed by the method invoked from debugger + public static final int INITIAL_VALUE = 10; + public static final int FINAL_VALUE = 1234; + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + invokemeth001a _invokemeth001a = new invokemeth001a(); + System.exit(invokemeth001.JCK_STATUS_BASE + _invokemeth001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested of tested class + log.display("Creating object of tested class"); + TestedObjectClass foo = new TestedObjectClass(); + log.display(" ... object created"); + + // run method with breakpoint + TestedObjectClass.run(); + + log.display("Debugee PASSED"); + return invokemeth001.PASSED; + } + + // tested object class + public static class TestedObjectClass { + // result of invoking tested mathod + public static volatile int result = INITIAL_VALUE; + + // suspend current thread on breakpoint + public static void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE_NUMBER + log.display("Breakpoint line passed"); + + log.display("Tested thread: finished"); + } + + // tested method for invocation from debugger + public static int testedMethod(int arg) { + log.display("Tested method invoked with argument:" + arg); + int old = result; + result = arg; + log.display("Tested method returned with result:" + old); + return old; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassType.NewInstance; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ClassType.NewInstance. + * + * See newinst001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class newinst001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names + static final String PACKAGE_NAME = "nsk.jdwp.ClassType.NewInstance"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "newinst001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command + static final String JDWP_COMMAND_NAME = "ClassType.NewInstance"; + static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.NewInstance; + + // tested class name and signature + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // field and method names + static final String RESULT_FIELD_NAME = "result"; + static final String TESTED_CONSTRUCTOR_NAME = ""; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE_NUMBER = newinst001a.BREAKPOINT_LINE_NUMBER; + + // data for invoked method + static final int ARGUMENTS_COUNT = 1; + static final int INITIAL_VALUE = newinst001a.INITIAL_VALUE; + static final int ARGUMENT_VALUE = newinst001a.FINAL_VALUE; + static final int RETURN_VALUE = INITIAL_VALUE; + static final int INVOKE_OPTIONS = 0; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + boolean dead = false; + + // data obtained from debuggee + long classID = 0; + long threadID = 0; + long methodID = 0; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new newinst001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee VM"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debuggee launched"); + + // set timeout for debuggee responces + int waitTime = argumentHandler.getWaitTime(); // minutes + long timeout = waitTime * 60 * 1000; // milliseconds + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for VM_INIT event + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // run the test + runTest(); + + // wait for VM_DEATH event + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + log.display(" ... VM_DEATH event received"); + dead = true; + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + log.display("\n>>> Finishing test \n"); + + // disconnect debugee and wait for its exit + if (debugee != null) { + quitDebugee(); + } + } + + // check result + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + out.println("TEST PASSED"); + return PASSED; + } + + /** + * Obtain required data and test JDWP command. + */ + void runTest() { + log.display("\n>>> Obtaining required data \n"); + + // wait for tested class loaded on debuggee startup and obtain its classID + log.display("Waiting for class loaded:\n\t" + TESTED_CLASS_NAME); + classID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + classID); + log.display(""); + + // query debuggee for tested methodID + log.display("Getting tested methodID by constructor name: " + TESTED_CONSTRUCTOR_NAME); + methodID = debugee.getMethodID(classID, TESTED_CONSTRUCTOR_NAME, true); + log.display(" ... got methodID: " + methodID); + log.display(""); + + // set breakpoint and wait for debugee reached it + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_NUMBER); + threadID = debugee.waitForBreakpointReached(classID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE_NUMBER, + JDWP.SuspendPolicy.EVENT_THREAD); + log.display(" ... breakpoint reached with threadID: " + threadID); + + // test JDWP command + log.display("\n>> Testing JDWP command \n"); + testCommand(); + + // check command results + if (success) { + log.display("\n>>> Checking command results \n"); + checkResult(); + } + + // resume debuggee after the command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" classID: " + classID); + command.addReferenceTypeID(classID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + log.display(" arguments: " + ARGUMENTS_COUNT); + command.addInt(ARGUMENTS_COUNT); + for (int i = 0; i < ARGUMENTS_COUNT; i++) { + JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); + log.display(" arg: " + value); + command.addValue(value); + } + log.display(" options: " + INVOKE_OPTIONS); + command.addInt(INVOKE_OPTIONS); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet for tested command:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // extract return value + JDWP.Value newObject = null; + try { + newObject = reply.getValue(); + log.display(" newObject: " + newObject); + } catch (BoundException e) { + log.complain("Unable to extract returnValues from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract exception tag + JDWP.Value exception = null; + try { + exception = reply.getValue(); + log.display(" exception: " + exception); + } catch (BoundException e) { + log.complain("Unable to extract exception from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... packed data parsed"); + + // check that return value is an integer + if (newObject.getTag() != JDWP.Tag.OBJECT) { + log.complain("Unexpected tag of returnValue returned: " + newObject.getTag() + + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // check that return value is as expected + long newObjectID = ((Long)newObject.getValue()).longValue(); + if (newObjectID == 0) { + log.complain("Unexpected null objectID for newObject value returned: " + + newObjectID + " (expected: not " + 0 + ")"); + success = false; + } + + // check that exception value is an object + if (exception.getTag() != JDWP.Tag.OBJECT) { + log.complain("Unexpected tag of exception returned: " + exception.getTag() + + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // check that exception object is null + long exceptionID = ((Long)exception.getValue()).longValue(); + if (exceptionID != 0) { + log.complain("Not null objectID for exception value returned: " + exceptionID + + " (expected: " + 0 + ")"); + success = false; + } + } + + /** + * Check result of the tested JDWP command. + */ + void checkResult() { + // query debuggee for result value from a static field + log.display("Getting result value from static field: " + RESULT_FIELD_NAME); + int result = queryInt(classID, RESULT_FIELD_NAME, JDWP.Tag.INT); + log.display(" ... got result: " + result); + + // check if the result value is changed as expected + if (result != ARGUMENT_VALUE) { + log.complain("Method has not been really invoked: \n\t" + + "variable not changed by the method: " + result + + " (expected: " + ARGUMENT_VALUE + ")"); + success = false; + } else { + log.display("Method has been really invoked: \n\t" + + " variable changed by the method: " + result + + " (expected: " + ARGUMENT_VALUE + ")"); + } + } + + /** + * Query debuggee for value of static field of the class. + */ + JDWP.Value queryFieldValue(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + log.complain("unexpedted value tag returned from debuggee: " + value.getTag() + + " (expected: " + tag + ")"); + throw new Failure("Error occured while getting value from static field: " + + fieldName); + } + + return value; + } + + /** + * Query debuggee for objectID value of static field of the class. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + JDWP.Value value = queryFieldValue(classID, fieldName, tag); + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Query debuggee for int value of static field of the class. + */ + int queryInt(long classID, String fieldName, byte tag) { + JDWP.Value value = queryFieldValue(classID, fieldName, tag); + int intValue = ((Integer)value.getValue()).intValue(); + return intValue; + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debuggee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally dispose debuggee:\n\t" + e.getMessage()); + } + } + + // wait for debugee exits + log.display("Waiting for debuggee exits"); + int code = debugee.waitFor(); + log.display(" ... debuggee finished with exit code: " + code); + + // analize debuggee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ClassType/NewInstance/newinst001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ClassType + * command: NewInstance + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the tested constructor is really invoked into debuggee. + * Test consists of two compoments: + * debugger: newinst001 + * debuggee: newinst001a + * First, debugger uses nsk.share.* support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded, requests methodID + * for tested constructtor, sets breakpoint and wait for breakpoint reached. + * When breakpoint event is received the tested thread into debuggee + * is suspended by this event. + * Then, debugger creates command packet for classType.NewInstance + * command with the found classID, methodID, threadID, and also adds one + * integer argument for the constructor invocation. Then debugger writes + * packet to the transport channel and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts tegged objectID's of new created object and exception. + * Test checks if objectID is not null and exception objectID is null. + * Also test gets value of static field, wich should be modified by + * the invoked constructor, to verify if this constructor was really + * invoked into debuggee. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ClassType.NewInstance.newinst001 + * nsk.jdwp.ClassType.NewInstance.newinst001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ClassType.NewInstance.newinst001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.ClassType.NewInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class newinst001a { + + // name of the tested thread + public static final String THREAD_NAME = "testedThread"; + + // line nunber for breakpoint + public static final int BREAKPOINT_LINE_NUMBER = 88; + + // initial and final value of variable changed by the method invoked from debugger + public static final int INITIAL_VALUE = 10; + public static final int FINAL_VALUE = 1234; + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + newinst001a _newinst001a = new newinst001a(); + System.exit(newinst001.JCK_STATUS_BASE + _newinst001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested of tested class + log.display("Accessing to tested class"); + TestedObjectClass.foo = 100; + log.display(" ... class loaded"); + + // invoke method with breakpoint + TestedObjectClass.run(); + + log.display("Debugee PASSED"); + return newinst001.PASSED; + } + + // tested object class + public static class TestedObjectClass { + public static int foo = 0; + + // result of invoking tested mathod + public static volatile int result = INITIAL_VALUE; + + // suspend current thread on on breakpoint + public static void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE_NUMBER + log.display("Breakpoint line passed"); + + log.display("Tested thread: finished"); + } + + // tested constructor for invokation from debugger + public TestedObjectClass(int arg) { + log.display("Tested constructor invoked with argument:" + arg); + if (arg != FINAL_VALUE) { + log.complain("Unexpected value of constructor argument: " + arg + + " (expected: " + FINAL_VALUE + ")"); + } + result = arg; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassType.SetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ClassType.SetValues. + * + * See setvalues001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class setvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String RUN = "run"; + static final String DONE = "done"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ClassType.SetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "setvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ClassType.SetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.SetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // target values class name and signature constants + static final String TARGET_VALUES_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TargetValuesClass"; + static final String TARGET_VALUES_CLASS_SIGNATURE = "L" + TARGET_VALUES_CLASS_NAME.replace('.', '/') + ";"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new setvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for classID for the class with target values + log.display("Getting classID for class with target values by signature:\n" + + " " + TARGET_VALUES_CLASS_SIGNATURE); + long targetValuesClassID = + debugee.getReferenceTypeID(TARGET_VALUES_CLASS_SIGNATURE); + log.display(" got classID: " + targetValuesClassID); + + // query debugee for fieldIDs of the class static fields + log.display("Getting fieldIDs for static fields of the class"); + long targetValuesFieldIDs[] = queryClassFieldIDs(targetValuesClassID); + log.display(" got fields: " + targetValuesFieldIDs.length); + int count = targetValuesFieldIDs.length; + + // query debugee for values of the fields + log.display("Getting values of the static fields"); + JDWP.Value targetValues[] = + queryClassFieldValues(targetValuesClassID, targetValuesFieldIDs); + log.display(" got values: " + targetValues.length); + if (targetValues.length != count) { + throw new Failure("Unexpected number of static fields values received: " + + targetValues.length + "(expected: " + count + ")"); + } + + // query debugee for classID of the tested class + log.display("Getting tested classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long testedClassID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + testedClassID); + + // query debugee for fieldIDs of tested class static fields + log.display("Getting fieldIDs for static fields of the tested class"); + long testedFieldIDs[] = queryClassFieldIDs(testedClassID); + log.display(" got fields: " + testedFieldIDs.length); + if (testedFieldIDs.length != count) { + throw new Failure("Unexpected number of static fields of tested class received: " + + testedFieldIDs.length + "(expected: " + count + ")"); + } + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(testedClassID, testedFieldIDs, targetValues); + + // check confirmation from debuggee that values have been set properly + log.display("\n>>> Checking that the values have been set properly \n"); + checkValuesChanged(); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debugee for fieldID's of the class static fields. + */ + long[] queryClassFieldIDs(long classID) { + // compose ReferenceType.Fields command packet + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(classID); + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract fieldIDs from the reply packet + try { + reply.resetPosition(); + + int declared = reply.getInt(); + long[] fieldIDs = new long[declared]; + + for (int i = 0; i < declared; i++ ) { + long fieldID = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + fieldIDs[i] = fieldID; + } + return fieldIDs; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.Fields command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fieldIDs for classID: " + classID); + } + } + + /** + * Query debugee for values of the class static fields. + */ + JDWP.Value[] queryClassFieldValues(long classID, long fieldIDs[]) { + // compose ReferenceType.Fields command packet + int count = fieldIDs.length; + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.GetValues); + command.addReferenceTypeID(classID); + command.addInt(count); + for (int i = 0; i < count; i++) { + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract values from the reply packet + try { + reply.resetPosition(); + + int valuesCount = reply.getInt(); + JDWP.Value values[] = new JDWP.Value[valuesCount]; + for (int i = 0; i < valuesCount; i++ ) { + JDWP.Value value = reply.getValue(); + values[i] = value; + } + return values; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.GetValues command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fields values for classID: " + classID); + } + } + + /** + * Perform testing JDWP command for specified classID. + */ + void testCommand(long classID, long fieldIDs[], JDWP.Value values[]) { + int count = fieldIDs.length; + + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" classID: " + classID); + command.addReferenceTypeID(classID); + log.display(" values: " + count); + command.addInt(count); + for (int i = 0; i < count; i++) { + log.display(" field #" + i +":"); + log.display(" fieldID: " + fieldIDs[i]); + command.addFieldID(fieldIDs[i]); + + JDWP.Value value = values[i]; + JDWP.UntaggedValue untaggedValue = + new JDWP.UntaggedValue(value.getValue()); + log.display(" untagged_value: " + untaggedValue.getValue()); + command.addUntaggedValue(untaggedValue, value.getTag()); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no data to extract + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + + /** + * Check confiramtion from debuggee that values are changed. + */ + void checkValuesChanged() { + // send debugee signal RUN + log.display("Sending signal to debugee: " + RUN); + pipe.println(RUN); + + // wait for DONE signal from debugee + log.display("Waiting for signal from debugee: " + DONE); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + // check received signal + if (signal == null) { + throw new TestBug(" signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } else if (signal.equals(DONE)) { + log.display("All static fields values have been correctly set into debuggee VM"); + } else if (signal.equals(ERROR)) { + log.complain("Not all static fields values have been correctly set into debuggee VM"); + success = false; + } else { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ClassType/SetValues/setvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ClassType + * command: SetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the values are correctly set to debuggee class fields. + * Test consists of two compoments: + * debugger: setvalues001 + * debuggee: setvalues001a + * To set values to the static fields of the tested class + * and check that they are set correctly, test defines + * following classes into debuggee VM: + * OriginalValuesClass - with original values of static fields + * TargetValuesClass - with target values of static fields + * TestedClass - tested class with static fields to set values to + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains classIDs for the tested class and class with + * the target values from debugee, it obtains also fieldIDs for thess + * classese and target values of the fields. + * Then, debugger creates command packet for SetValues command with the + * found referenceTypeID and list of fieldIDs as arguments, writes packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and and checks that there is no data in the reply packet. + * Then debugger sends signal RUN to debuggee to ask it to verify + * new fields values of tested class. Debuggee compares compares + * these values with original and terget values and sends ERROR signal + * to debugger if the values was not set correctly. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ClassType.SetValues.setvalues001 + * nsk.jdwp.ClassType.SetValues.setvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ClassType.SetValues.setvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassType.SetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part of the test. + */ +public class setvalues001a { + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + setvalues001a _setvalues001a = new setvalues001a(); + System.exit(setvalues001.JCK_STATUS_BASE + _setvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + // make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of all required classes"); + OriginalValuesClass original = new OriginalValuesClass(); + TargetValuesClass target = new TargetValuesClass(); + TestedClass tested = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + setvalues001.READY); + pipe.println(setvalues001.READY); + + // wait for signal RUN from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.RUN); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + // check received signal + if (signal == null || !signal.equals(setvalues001.RUN)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.RUN + ")"); + log.display("Debugee FAILED"); + return setvalues001.FAILED; + } + + // check assigned values + if (checkValues()) { + log.display("Sending signal to debugger: " + setvalues001.DONE); + pipe.println(setvalues001.DONE); + } else { + log.display("Sending signal to debugger: " + setvalues001.ERROR); + pipe.println(setvalues001.ERROR); + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.QUIT); + signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + // check received signal + if (! signal.equals(setvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.QUIT + ")"); + log.display("Debugee FAILED"); + return setvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return setvalues001.PASSED; + } + + // check values of static fields for both classes + static boolean checkValues() { + int different = 0; + log.display("Checking that values have been set correctly:"); + + // check value of the field + if (TestedClass.booleanValue != TargetValuesClass.booleanValue) { + different++; + log.complain(" booleanValue = " + TestedClass.booleanValue + "\n" + + " setting: " + OriginalValuesClass.booleanValue + + " -> " + TargetValuesClass.booleanValue); + if (TestedClass.booleanValue == OriginalValuesClass.booleanValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" booleanValue: " + OriginalValuesClass.booleanValue + + " -> " + TargetValuesClass.booleanValue); + } + + // check value of the field + if (TestedClass.byteValue != TargetValuesClass.byteValue) { + different++; + log.complain(" byteValue = " + TestedClass.byteValue + "\n" + + " setting: " + OriginalValuesClass.byteValue + + " -> " + TargetValuesClass.byteValue); + if (TestedClass.byteValue == OriginalValuesClass.byteValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" byteValue: " + OriginalValuesClass.byteValue + + " -> " + TargetValuesClass.byteValue); + } + + // check value of the field + if (TestedClass.charValue != TargetValuesClass.charValue) { + different++; + log.complain(" charValue = " + TestedClass.charValue + "\n" + + " setting: " + OriginalValuesClass.charValue + + " -> " + TargetValuesClass.charValue); + if (TestedClass.charValue == OriginalValuesClass.charValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" charValue: " + OriginalValuesClass.charValue + + " -> " + TargetValuesClass.charValue); + } + + // check value of the field + if (TestedClass.intValue != TargetValuesClass.intValue) { + different++; + log.complain(" intValue = " + TestedClass.intValue + "\n" + + " setting: " + OriginalValuesClass.intValue + + " -> " + TargetValuesClass.intValue); + if (TestedClass.intValue == OriginalValuesClass.intValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" intValue: " + OriginalValuesClass.intValue + + " -> " + TargetValuesClass.intValue); + } + + // check value of the field + if (TestedClass.shortValue != TargetValuesClass.shortValue) { + different++; + log.complain(" shortValue = " + TestedClass.shortValue + "\n" + + " setting: " + OriginalValuesClass.shortValue + + " -> " + TargetValuesClass.shortValue); + if (TestedClass.shortValue == OriginalValuesClass.shortValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" shortValue: " + OriginalValuesClass.shortValue + + " -> " + TargetValuesClass.shortValue); + } + // check value of the field + if (TestedClass.longValue != TargetValuesClass.longValue) { + different++; + log.complain(" longValue = " + TestedClass.longValue + "\n" + + " setting: " + OriginalValuesClass.longValue + + " -> " + TargetValuesClass.longValue); + if (TestedClass.longValue == OriginalValuesClass.longValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" longValue: " + OriginalValuesClass.longValue + + " -> " + TargetValuesClass.longValue); + } + // check value of the field + if (TestedClass.floatValue != TargetValuesClass.floatValue) { + different++; + log.complain(" floatValue = " + TestedClass.floatValue + "\n" + + " setting: " + OriginalValuesClass.floatValue + + " -> " + TargetValuesClass.floatValue); + if (TestedClass.floatValue == OriginalValuesClass.floatValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" floatValue: " + OriginalValuesClass.floatValue + + " -> " + TargetValuesClass.floatValue); + } + // check value of the field + if (TestedClass.doubleValue != TargetValuesClass.doubleValue) { + different++; + log.complain(" doubleValue = " + TestedClass.doubleValue + "\n" + + " setting: " + OriginalValuesClass.doubleValue + + " -> " + TargetValuesClass.doubleValue); + if (TestedClass.doubleValue == OriginalValuesClass.doubleValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" doubleValue: " + OriginalValuesClass.doubleValue + + " -> " + TargetValuesClass.doubleValue); + } + + // check value of the field + if (TestedClass.stringValue != TargetValuesClass.stringValue) { + different++; + log.complain(" stringValue = " + TestedClass.stringValue + "\n" + + " setting: " + OriginalValuesClass.stringValue + + " -> " + TargetValuesClass.stringValue); + if (TestedClass.stringValue == OriginalValuesClass.stringValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" stringValue: " + OriginalValuesClass.stringValue + + " -> " + TargetValuesClass.stringValue); + } + + // check value of the field + if (TestedClass.objectValue != TargetValuesClass.objectValue) { + different++; + log.complain(" objectValue = " + TestedClass.objectValue + "\n" + + " setting: " + OriginalValuesClass.objectValue + + " -> " + TargetValuesClass.objectValue); + if (TestedClass.objectValue == OriginalValuesClass.objectValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" objectValue: " + OriginalValuesClass.objectValue + + " -> " + TargetValuesClass.objectValue); + } + +/* + // check value of the field + if (TestedClass.Value != TargetValuesClass.Value) { + different++; + log.complain(" Value = " + TestedClass.Value + "\n" + + " setting: " + OriginalValuesClass.Value + + " -> " + TargetValuesClass.Value); + if (TestedClass.Value == OriginalValuesClass.Value) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" Value: " + OriginalValuesClass.Value + + " -> " + TargetValuesClass.Value); + } +*/ + + // check taht no any changed value differs from target + if (different > 0) { + log.complain("Values of " + different + " fields have not been set correctly"); + return false; + } + + log.display("Values of all fields have been set correctly"); + return true; + } + + // class with the original values of static fields + public static class OriginalValuesClass { + static final boolean booleanValue = true; + static final byte byteValue = (byte)0x01; + static final char charValue = 'Z'; + static final int intValue = 100; + static final short shortValue = (short)10; + static final long longValue = (long)1000000; + static final float floatValue = (float)3.14; + static final double doubleValue = (double)2.8e-12; + static final String stringValue = "text"; + static final Object objectValue = new OriginalValuesClass(); + } + + // class with the original values of static fields + public static class TargetValuesClass { + static final boolean booleanValue = false; + static final byte byteValue = (byte)0x0F; + static final char charValue = 'A'; + static final int intValue = 999; + static final short shortValue = (short)88; + static final long longValue = (long)11111111; + static final float floatValue = (float)7.19; + static final double doubleValue = (double)4.6e24; + static final String stringValue = "new text"; + static final Object objectValue = new TargetValuesClass(); + } + + // tested class with own static fields values + public static class TestedClass { + private static boolean booleanValue = OriginalValuesClass.booleanValue; + private static byte byteValue = OriginalValuesClass.byteValue; + protected static char charValue = OriginalValuesClass.charValue; + protected static int intValue = OriginalValuesClass.intValue; + public static short shortValue = OriginalValuesClass.shortValue; + public static long longValue = OriginalValuesClass.longValue; + static float floatValue = OriginalValuesClass.floatValue; + static double doubleValue = OriginalValuesClass.doubleValue; + static String stringValue = OriginalValuesClass.stringValue; + static Object objectValue = OriginalValuesClass.objectValue; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassType.Superclass; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ClassType.Superclass. + * + * See superclass001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class superclass001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ClassType.Superclass"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "superclass001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ClassType.Superclass"; + static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.Superclass; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // tested superclass name and signature constants + static final String TESTED_SUPERCLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "Superclass"; + static final String TESTED_SUPERCLASS_SIGNATURE = "L" + TESTED_SUPERCLASS_NAME.replace('.', '/') + ";"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new superclass001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for classID of tested class + log.display("Getting classID of tested class by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debugee for classID of tested superclass + log.display("Getting classID of tested superclass by signature:\n" + + " " + TESTED_SUPERCLASS_SIGNATURE); + long superclassID = debugee.getReferenceTypeID(TESTED_SUPERCLASS_SIGNATURE); + log.display(" got classID: " + superclassID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classID, superclassID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified classID's. + */ + void testCommand(long classID, long superclassID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + log.display(" ClassID: " + classID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(classID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check superclass ID + try { + long superclass = reply.getReferenceTypeID(); + log.display(" superclass: " + superclass); + + if (superclass != superclassID) { + log.complain("Unexpected classID for superclass in the reply packet:" + superclass + + " (expected: " + superclassID + ")"); + success = false; + } + } catch (BoundException e) { + log.complain("Unable to extract superclass ID from reply packet:\n" + e.getMessage()); + success = false; + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ClassType/Superclass/superclass001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ClassType + * command: Superclass + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test check that the + * returned classID for a superclass is equal to the expected one. + * Test consists of two compoments: + * debugger: superclass001 + * debuggee: superclass001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger prepares for testing JDWP command and obtains + * classID's for the tested class and its superclass. + * Then, debugger creates command packet for Superclass command with the + * found classID as an argument, writes packet to the transport channel, + * and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts classID of a superclass. Also test checks that extracted + * classID for a superclass is equal to the expected one. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ClassType.Superclass.superclass001 + * nsk.jdwp.ClassType.Superclass.superclass001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ClassType.Superclass.superclass001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ClassType.Superclass; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class superclass001a { + + public static void main(String args[]) { + superclass001a _superclass001a = new superclass001a(); + System.exit(superclass001.JCK_STATUS_BASE + _superclass001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + superclass001.READY); + pipe.println(superclass001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + superclass001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(superclass001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + superclass001.QUIT + ")"); + log.display("Debugee FAILED"); + return superclass001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return superclass001.PASSED; + } + + // indirect superclass for tested class + public static class IndirectSuperclass { + int foo = 0; + public IndirectSuperclass() { + foo = 100; + } + } + + // direct superclass for tested class + public static class Superclass extends IndirectSuperclass { + public Superclass() { + super(); + } + } + + // tested class + public static class TestedClass extends Superclass { + public TestedClass() { + super(); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,653 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.BREAKPOINT; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: BREAKPOINT. + * + * See breakpoint001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class breakpoint001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.BREAKPOINT"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "breakpoint001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.BREAKPOINT; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = breakpoint001a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new breakpoint001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + + // request tested event + log.display("Making request for BREAKPOINT event at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested BREAKPOINT event + log.display("Waiting for BREAKPOINT event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // check if event is for expected thread + if (success) { + log.display("Checking thread of BREAKPOINT event"); + checkThread(); + log.display(""); + } + + + // clear tested request for BREAKPOINT event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for tested method + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for breakpoint line + log.display("Getting codeIndex for breakpoint line: " + BREAKPOINT_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, BREAKPOINT_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for breakpoint + log.display("Creating location for breakpoint request"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + } + + /** + * Make request for tested BREAKPOINT event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.LOCATION_ONLY); + command.addByte(JDWP.EventModifierKind.LOCATION_ONLY); + log.display(" location: " + testedLocation); + command.addLocation(testedLocation); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested BREAKPOINT event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested BREAKPOINT event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.BREAKPOINT + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.BREAKPOINT) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.BREAKPOINT + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // save threadID for further checking + testedThreadID = threadID; + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + if (location.getTag() != testedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + i + + " in tested event packet: " + location.getTag() + + " (expected: " + testedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != testedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + i + + " in tested event packet: " + location.getClassID() + + " (expected: " + testedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != testedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + i + + " in tested event packet: " + location.getMethodID() + + " (expected: " + testedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != testedLocation.getIndex()) { + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + testedLocation.getIndex() + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Check if threadID received by BREAKPOINT event is as expected one. + */ + void checkThread() { + // get thread value from static field of tested class + log.display("Getting thread value from static field: " + THREAD_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, THREAD_FIELD_NAME, + JDWP.Tag.THREAD); + long threadID = ((Long)value.getValue()).longValue(); + log.display(" ... got threadID: " + testedThreadID); + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of BREAKPOINT event received: " + + testedThreadID + " (expected: " + threadID + ")"); + success = false; + } else { + log.display("Received threadID is as expected"); + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/BREAKPOINT/breakpoint001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: BREAKPOINT + * Test checks that + * 1) debuggee successfully creates BREAKPOINT event request + * for particular location + * 2) expected BREAKPOINT event is received when the thread + * reaches breakpoint and has correct attributes + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: breakpoint001 + * debuggee: breakpoint001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and makes BREAKPOINT + * event request for location into method run() of the tested thread, + * When event is received debugger checks if the received event + * is for this location and has correct attributes. Then debugger + * removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.BREAKPOINT.breakpoint001 + * nsk.jdwp.Event.BREAKPOINT.breakpoint001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.BREAKPOINT.breakpoint001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.BREAKPOINT; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class breakpoint001a { + + static final int BREAKPOINT_LINE = 91; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + breakpoint001a _breakpoint001a = new breakpoint001a(); + System.exit(breakpoint001.JCK_STATUS_BASE + _breakpoint001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass.thread = new TestedClass(breakpoint001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + TestedClass.thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + TestedClass.thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return breakpoint001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return breakpoint001.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public static volatile TestedClass thread = null; + + public TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + log.display("Tested thread: finished"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,607 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.CLASS_PREPARE; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: CLASS_PREPARE. + * + * See clsprepare001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class clsprepare001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.CLASS_PREPARE"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clsprepare001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.CLASS_PREPARE; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new clsprepare001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // make request for CLASS_PREPARE event + log.display("\n>>> Making request for tested event \n"); + + log.display("Making request for CLASS_PREPARE event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for tested CLASS_PREPARE event + log.display("\n>>> Testing JDWP event \n"); + waitForTestedEvent(); + + // clear tested request for CLASS_PREPARE event + log.display("\n>>> Clearing request for tested event \n"); + clearTestedRequest(); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Make request for tested CLASS_PREPARE event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.CLASS_MATCH); + command.addByte(JDWP.EventModifierKind.CLASS_MATCH); + log.display(" classPattern: " + TESTED_CLASS_NAME); + command.addString(TESTED_CLASS_NAME); + command.setLength(); + log.display(" ... command packet composed"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested CLASS_PREPARE event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested CLASS_PREPARE event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet (for " + timeout + "ms timeout)"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind != JDWP.EventKind.CLASS_PREPARE) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.CLASS_PREPARE + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID == 0) { + log.complain("Unexpected null threadID of event " + i + " in tested event packet: " + + threadID); + success = false; + } + + // get refTypeTag + byte refTypeTag = 0; + try { + refTypeTag = eventPacket.getByte(); + log.display(" refTypeTag: " + refTypeTag); + } catch (BoundException e) { + log.complain("Unable to get refTypeTag of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check refTypeGag + if (refTypeTag != JDWP.TypeTag.CLASS) { + log.complain("Unexpected refTypeTag of event " + i + " in tested event packet: " + + refTypeTag + " (expected: " + JDWP.TypeTag.CLASS + ")"); + success = false; + } + + // get referenceTypeID + long referenceTypeID = 0; + try { + referenceTypeID = eventPacket.getReferenceTypeID(); + log.display(" referenceTypeID: " + referenceTypeID); + } catch (BoundException e) { + log.complain("Unable to get referenceTypeID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check referenceTypeID + if (referenceTypeID == 0) { + log.complain("Unexpected null referenceTypeID of event " + i + " in tested event packet: " + + referenceTypeID); + success = false; + } + + // get signature + String signature = null; + try { + signature = eventPacket.getString(); + log.display(" signature: " + signature); + } catch (BoundException e) { + log.complain("Unable to get class signature of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check signature + if (!signature.equals(TESTED_CLASS_SIGNATURE)) { + log.complain("Unexpected class signature of event " + i + " in tested event packet: " + + signature + " (expected: " + TESTED_CLASS_SIGNATURE + ")"); + success = false; + } + + // get status + int status = 0; + try { + status = eventPacket.getInt(); + log.display(" status: " + status); + } catch (BoundException e) { + log.complain("Unable to get class status of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check status + if ((status & JDWP.ClassStatus.ERROR) != 0) { + log.complain("Unexpected class status of event " + i + " in tested event packet: " + + status + " (expected: w/o bit " + JDWP.ClassStatus.ERROR + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/CLASS_PREPARE/clsprepare001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: CLASS_PREPARE + * Test checks that + * 1) debuggee successfully creates CLASS_PREPARE event request + * for tested class name + * 2) expected CLASS_PREPARE event is received when this class + * is loaded at the debuggee's startup. + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: thrstart001 + * debuggee: thrstart001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger makes CLASS_PREPARE event request for tested class + * and resumes debuggee to permit it to load classes. + * When expected CLASS_PREPARE event is received debugger checks + * if this event is for tested class and has correct attributes. + * Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.CLASS_PREPARE.clsprepare001 + * nsk.jdwp.Event.CLASS_PREPARE.clsprepare001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.CLASS_PREPARE.clsprepare001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.CLASS_PREPARE; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class clsprepare001a { + + public static void main(String args[]) { + clsprepare001a _clsprepare001a = new clsprepare001a(); + System.exit(clsprepare001.JCK_STATUS_BASE + _clsprepare001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display(" ... object created"); + + // exit debugee + log.display("Debugee PASSED"); + return clsprepare001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.CLASS_UNLOAD; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: CLASS_UNLOAD. + * + * See clsunload001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class clsunload001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.CLASS_UNLOAD"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clsunload001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.CLASS_UNLOAD; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new clsunload001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // make request for CLASS_UNLOAD event + log.display("\n>>> Making request for tested event \n"); + + log.display("Making request for CLASS_UNLOAD event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for tested CLASS_UNLOAD event + log.display("\n>>> Testing JDWP event \n"); + waitForTestedEvent(); + + if (!dead) { + // clear tested request for CLASS_UNLOAD event + log.display("\n>>> Clearing request for tested event \n"); + clearTestedRequest(); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Make request for tested CLASS_UNLOAD event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.CLASS_MATCH); + command.addByte(JDWP.EventModifierKind.CLASS_MATCH); + log.display(" classPattern: " + TESTED_CLASS_NAME); + command.addString(TESTED_CLASS_NAME); + command.setLength(); + log.display(" ... command packet composed"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested CLASS_UNLOAD event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested CLASS_UNLOAD event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet (for " + timeout + "ms timeout)"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check if VM_DEATH event + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Got VM_DEATH event while waiting for tested event"); + dead = true; + log.println("No CLASS_UNLOAD event occured at all so treat test as PASSED"); + return; + } + + // check eventKind + if (eventKind != JDWP.EventKind.CLASS_UNLOAD) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.CLASS_UNLOAD + ")"); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get signature + String signature = null; + try { + signature = eventPacket.getString(); + log.display(" signature: " + signature); + } catch (BoundException e) { + log.complain("Unable to get class signature of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check signature + if (!signature.equals(TESTED_CLASS_SIGNATURE)) { + log.complain("Unexpected class signature of event " + i + " in tested event packet: " + + signature + " (expected: " + TESTED_CLASS_SIGNATURE + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/CLASS_UNLOAD/clsunload001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: CLASS_UNLOAD + * Test checks that + * 1) debuggee successfully creates CLASS_UNLOAD event request + * for particular class name + * 2) expected CLASS_UNLOAD event is received if this class is + * unloaded at debuggee's exit + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: clsunload001 + * debuggee: clsunload001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger makes request for CLASS_UNLOAD event for tested class, + * and resumes debuggee to permit it to exit. + * If expected CLASS_UNLOAD event is received debugger checks that + * this event if for tested class and has correct attributes. + * If no CLASS_UNLOAD event occures, tests pass anyway. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * Test was fixed due to test bug: + * 4864576 TEST_BUG: copy/paste error in JDWP test clsunload001 + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.CLASS_UNLOAD.clsunload001 + * nsk.jdwp.Event.CLASS_UNLOAD.clsunload001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.CLASS_UNLOAD.clsunload001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.CLASS_UNLOAD; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class clsunload001a { + + public static void main(String args[]) { + clsunload001a _clsunload001a = new clsunload001a(); + System.exit(clsunload001.JCK_STATUS_BASE + _clsunload001a.runIt(args, System.err)); +// _clsunload001a.runIt(args, System.err); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display(" ... object created"); + + // exit debugee + log.display("Debugee PASSED"); + return clsunload001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.Composite; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Event.Composite. + * + * See composite001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class composite001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.Composite"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "composite001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Event.Composite"; + static final int JDWP_COMMAND_ID = JDWP.Command.Event.Composite; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.VM_START; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new composite001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // test JDWP command + log.display("\n>>> Testing JDWP event \n"); + testCommand(); + + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" suspendPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" events: " + 1); + command.addInt(1); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + 0); + command.addInt(0); + log.display(" threadID: " + 0); + command.addObjectID(0); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + log.display("Checking header of reply packet:"); + + // extract and check length field + int length = reply.getLength(); + log.display(" length: " + length); + if (length != reply.length()) { + log.complain("Unexpected value of length field in header of reply packet: " + + length + "(actual: " + reply.length() + ")"); + success = false; + } + + // extract and check id field + int id = reply.getPacketID(); + log.display(" id: " + id); + if (id != command.getPacketID()) { + log.complain("Unexpected value of id field in header of reply packet: " + + id + "(expected: " + command.getPacketID() + ")"); + success = false; + } + + // extract and check flags field + byte flags = reply.getFlags(); + log.display(" flags: " + flags); + if (flags != JDWP.Flag.REPLY_PACKET) { + log.complain("Unexpected value of flags field in header of reply packet: " + + flags + "(expected: " + JDWP.Flag.REPLY_PACKET + ")"); + success = false; + } + + // extract and check error field (should be not null!) + int error = reply.getErrorCode(); + log.display(" error: " + error); + if (error == JDWP.Error.NONE) { + log.complain("Unexpected null value of error field in header of reply packet: " + + error + "(expected: not " + JDWP.Error.NONE + ")"); + success = false; + } + + log.display(" ... packet header is parsed"); + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no out data + log.display(" no out data"); + + log.display(" ... packet data is parsed"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/Composite/composite001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * Test checks that debugee replies with some error code when command + * Event.Composite with correct event is sent to debugee, because + * only debuggee is permited to send such a command to debugger. + * Test consists of two compoments: + * debugger: composite001 + * debuggee: composite001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger creates command packet for Event.Composite command + * with VM_START event and sends it to debuggee. Then debugger reads + * reply packet and checks if an error code is in the packet header. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.Composite.composite001 + * nsk.jdwp.Event.Composite.composite001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.Composite.composite001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.Composite; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class composite001a { + + public static void main(String args[]) { + composite001a _composite001a = new composite001a(); + System.exit(composite001.JCK_STATUS_BASE + _composite001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // exit debugee + log.display("Debugee PASSED"); + return composite001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,747 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.EXCEPTION; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: EXCEPTION. + * + * See exception001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class exception001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.EXCEPTION"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "exception001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.EXCEPTION; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedThreadClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String EXCEPTION_FIELD_NAME = "exception"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final String THROW_METHOD_NAME = "methodForThrow"; + static final String CATCH_METHOD_NAME = "methodForCatch"; + static final int BREAKPOINT_LINE = exception001a.BREAKPOINT_LINE; + static final int EXCEPTION_THROW_LINE = exception001a.EXCEPTION_THROW_LINE; + static final int EXCEPTION_CATCH_LINE = exception001a.EXCEPTION_CATCH_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long catchMethodID = 0; + long throwMethodID = 0; + JDWP.Location throwLocation = null; + JDWP.Location catchLocation = null; + long exceptionObjectID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new exception001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for EXCEPTION event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested EXCEPTION event + log.display("Waiting for EXCEPTION event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for EXCEPTION event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for the exception throw method + log.display("Getting methodID for exception throw method: " + THROW_METHOD_NAME); + throwMethodID = debugee.getMethodID(testedClassID, THROW_METHOD_NAME, true); + log.display(" ... got methodID: " + throwMethodID); + + // get codeIndex for exception throw line + log.display("Getting codeIndex for exception throw line: " + EXCEPTION_THROW_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, throwMethodID, EXCEPTION_THROW_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for exception throw line + log.display("Creating location for exception throw"); + throwLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + throwMethodID, codeIndex); + log.display(" ... got location: " + throwLocation); + + // get methodID for the exception catch method + log.display("Getting methodID for exception catch method: " + CATCH_METHOD_NAME); + catchMethodID = debugee.getMethodID(testedClassID, CATCH_METHOD_NAME, true); + log.display(" ... got methodID: " + catchMethodID); + + // get codeIndex for exception catch line + log.display("Getting codeIndex for exception catch line: " + EXCEPTION_CATCH_LINE); + codeIndex = debugee.getCodeIndex(testedClassID, catchMethodID, EXCEPTION_CATCH_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for exception catch line + log.display("Creating location for exception catch"); + catchLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + catchMethodID, codeIndex); + log.display(" ... got location: " + catchLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + + // get excepion objectID value for static field + log.display("Getting exception objectID from static field: " + EXCEPTION_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, EXCEPTION_FIELD_NAME, JDWP.Tag.OBJECT); + exceptionObjectID = ((Long)value.getValue()).longValue(); + log.display(" ... got exception objectID: " + exceptionObjectID); + log.display(""); + } + + /** + * Make request for tested EXCEPTION event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.CLASS_ONLY + " (CLASS_ONLY)"); + command.addByte(JDWP.EventModifierKind.CLASS_ONLY); + log.display(" classID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested EXCEPTION event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested EXCEPTION event. + */ + void waitForTestedEvent() { + + // receive reply packet from debugee + EventPacket eventPacket = null; + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.EXCEPTION + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.EXCEPTION) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.EXCEPTION + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get throw location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" throw_location: " + location); + } catch (BoundException e) { + log.complain("Unable to get throw location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + checkLocation(location, throwLocation, i, EXCEPTION_THROW_LINE, "throw"); + + // get exception tag + byte tag = 0; + try { + tag = eventPacket.getByte(); + log.display(" exception_tag: " + tag); + } catch (BoundException e) { + log.complain("Unable to get exception tag of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check tag + if (tag != JDWP.Tag.OBJECT) { + log.complain("Unexpected exception tag of event " + i + " in tested event packet: " + + tag + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // get exception objectID + long objectID = 0; + try { + objectID = eventPacket.getObjectID(); + log.display(" exception_objectID: " + objectID); + } catch (BoundException e) { + log.complain("Unable to get exception objectID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (objectID != exceptionObjectID) { + log.complain("Unexpected exception objectID of event " + i + " in tested event packet: " + + objectID + " (expected: " + exceptionObjectID + ")"); + success = false; + } + + // get catch location + location = null; + try { + location = eventPacket.getLocation(); + log.display(" catch_location: " + location); + } catch (BoundException e) { + log.complain("Unable to get catch location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + checkLocation(location, catchLocation, i, EXCEPTION_CATCH_LINE, "catch"); + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Check if given location is equal to the expected one. + */ + void checkLocation(JDWP.Location location, JDWP.Location expectedLocation, + int eventNumber, int expectedLine, String kind) { + if (location.getTag() != expectedLocation.getTag()) { + log.complain("Unexpected class tag of " + kind + " location of event " + + eventNumber + " in tested event packet: " + location.getTag() + + " (expected: " + expectedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != expectedLocation.getClassID()) { + log.complain("Unexpected classID of " + kind + " location of event " + + eventNumber + " in tested event packet: " + location.getClassID() + + " (expected: " + expectedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != expectedLocation.getMethodID()) { + log.complain("Unexpected methodID of " + kind + " location of event " + + eventNumber + " in tested event packet: " + location.getMethodID() + + " (expected: " + expectedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != expectedLocation.getIndex()) { +/* + log.complain("Unexpected codeIndex of " + kind + " location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + expectedLocation.getIndex() + ")"); + success = false; +*/ + try { + // find approximate line number for location + int lineNumber = debugee.getLineNumber(location, true); + if (lineNumber != expectedLine) { + log.complain("Unexpected line number of " + kind + " location of event " + + eventNumber + " in tested event packet: " + lineNumber + + " (expected: " + expectedLine + ")"); + success = false; + } else { + log.display("Unexpected codeIndex of " + kind + " location: " + location.getIndex() + + " (expected: " + expectedLocation.getIndex() + ")"); + log.display("Though line number of catch location is as expected: " + + expectedLine); + } + } catch (Failure e) { + log.complain("Unable to get line number for " + kind + " location of event " + + eventNumber + " in tested event packet:\n\t" + e.getMessage()); + success = false; + } + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/EXCEPTION/exception001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: EXCEPTION + * Test checks that + * 1) debuggee successfully creates EXCEPTION event request + * occured for particular classID + * 2) expected EXCEPTION event is received when the exception + * is thrown into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: exception001 + * debuggee: exception001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and obtains expected + * locations for throw and catch clauses of the tested exception. + * Then debugger waits for a breakpoint for tested thread is reached, + * end makes request for EXCEPTION event for found classID. + * When event is received debugger checks if the received event is for + * expected request, thread, and has correct locations of throw and + * catch clauses. Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * The test was fixed due to the following bug: + * 4740123 Wrong exception catch location in ExceptionEvent + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.EXCEPTION.exception001 + * nsk.jdwp.Event.EXCEPTION.exception001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.EXCEPTION.exception001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.EXCEPTION; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class exception001a { + + static final int BREAKPOINT_LINE = 102; + static final int EXCEPTION_THROW_LINE = 114; + static final int EXCEPTION_CATCH_LINE = 121; // line number was changed due to 4740123 + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + exception001a _exception001a = new exception001a(); + System.exit(exception001.JCK_STATUS_BASE + _exception001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedThreadClass thread = new TestedThreadClass(exception001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // create tested exception + log.display("Creating tested exception object"); + TestedThreadClass.exception = new TestedExceptionClass("tested exception"); + log.display(" ... exception object created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return exception001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return exception001.PASSED; + } + + // tested class + public static class TestedThreadClass extends Thread { + + // static field with tested exception object + public static volatile TestedExceptionClass exception = null; + + public TestedThreadClass(String name) { + super(name); + } + + // reach breakpoint before testing exception + public void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + + methodForCatch(); + + log.display("Tested thread: finished"); + } + + // throw tested exception + public void methodForThrow() throws TestedExceptionClass { + log.display("Throwing tested exception:\n\t" + exception); + // next line is location of exception throw + throw exception; // EXCEPTION_THROW_LINE + } + + // catch tested exception + public void methodForCatch() { + try { + methodForThrow(); + } catch (TestedExceptionClass e) { // EXCEPTION_CATCH_LINE + // due to evaluation of 4740123: "the first instruction at the target + // of the exception is code to assign to the formal parameter" + log.display("Caught tested exception:\n\t" + e); + } + } + + } + + // tested exception class + public static class TestedExceptionClass extends Exception { + public TestedExceptionClass(String message) { + super(message); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,804 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.FIELD_ACCESS; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: FIELD_ACCESS. + * + * See fldaccess001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class fldaccess001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_WATCH_FIELD_ACCESS; + static final String VM_CAPABILITY_NAME = "canWatchFieldAccess"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.FIELD_ACCESS"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "fldaccess001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.FIELD_ACCESS; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String OBJECT_FIELD_NAME = "object"; + static final String VALUE_FIELD_NAME = "value"; + static final String TESTED_METHOD_NAME = "methodForAccess"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = fldaccess001a.BREAKPOINT_LINE; + static final int FIELD_ACCESS_LINE = fldaccess001a.FIELD_ACCESS_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + long testedFieldID = 0; + long testedObjectID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new fldaccess001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // check for VM capability + log.display("\n>>> Checking VM capability \n"); + log.display("Getting VM capability: " + VM_CAPABILITY_NAME); + boolean capable = debugee.getCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME); + log.display(" ... got VM capability: " + capable); + + // exit as PASSED if this capability is not supported + if (!capable) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for FIELD_ACCESS event for field: " + + VALUE_FIELD_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested FIELD_ACCESS event + log.display("Waiting for FIELD_ACCESS event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for FIELD_ACCESS event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded:\n\t" + TESTED_CLASS_NAME); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... class loaded with classID: " + testedClassID); + log.display(""); + + // get fieldID for the tested field + log.display("Getting tested fieldID for field name: " + VALUE_FIELD_NAME); + testedFieldID = debugee.getClassFieldID(testedClassID, VALUE_FIELD_NAME, true); + log.display(" ... got fieldID: " + testedFieldID); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for field access line + log.display("Getting codeIndex for field acccess line: " + FIELD_ACCESS_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, FIELD_ACCESS_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location for field access line"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + + // get objectID of the tested object from static field + log.display("Getting tested objectID from static field: " + OBJECT_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + testedObjectID = ((Long)value.getValue()).longValue(); + log.display(" ... got objectID: " + testedObjectID); + } + + /** + * Make request for tested FIELD_ACCESS event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.FIELD_ONLY + " (FIELD_ONLY)"); + command.addByte(JDWP.EventModifierKind.FIELD_ONLY); + log.display(" classID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + log.display(" fieldID: " + testedFieldID); + command.addFieldID(testedFieldID); +/* + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.CLASS_ONLY + " (CLASS_ONLY)"); + command.addByte(JDWP.EventModifierKind.CLASS_ONLY); + log.display(" classID: " + testedClassID); + command.addReferenceTypeID(testedClassID); +*/ + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested FIELD_ACCESS event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested FIELD_ACCESS event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.FIELD_ACCESS + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.FIELD_ACCESS) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.FIELD_ACCESS + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + checkLocation(location, testedLocation, i, FIELD_ACCESS_LINE); + + // get type tag + byte refTypeTag = 0; + try { + refTypeTag = eventPacket.getByte(); + log.display(" refTypeTag: " + refTypeTag); + } catch (BoundException e) { + log.complain("Unable to get reftypetag of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check type tag + if (refTypeTag != JDWP.TypeTag.CLASS) { + log.complain("Unexpected refTypeTag of event " + i + " in tested event packet: " + + refTypeTag + " (expected: " + JDWP.TypeTag.CLASS + ")"); + success = false; + } + + // get typeID + long typeID = 0; + try { + typeID = eventPacket.getReferenceTypeID(); + log.display(" typeID: " + typeID); + } catch (BoundException e) { + log.complain("Unable to get typeID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check typeID + if (typeID != testedClassID) { + log.complain("Unexpected typeID of event " + i + " in tested event packet: " + + typeID + " (expected: " + testedClassID + ")"); + success = false; + } + + // get fieldID + long fieldID = 0; + try { + fieldID = eventPacket.getFieldID(); + log.display(" fieldID: " + fieldID); + } catch (BoundException e) { + log.complain("Unable to get fieldID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check fieldID + if (fieldID != testedFieldID) { + log.complain("Unexpected fieldID of event " + i + " in tested event packet: " + + fieldID + " (expected: " + testedFieldID + ")"); + success = false; + } + + // get object tag + byte objectTag = 0; + try { + objectTag = eventPacket.getByte(); + log.display(" objectTag: " + objectTag); + } catch (BoundException e) { + log.complain("Unable to get object tag of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check object tag + if (objectTag != JDWP.Tag.OBJECT) { + log.complain("Unexpected object tag of event " + i + " in tested event packet: " + + objectTag + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // get objectID + long objectID = 0; + try { + objectID = eventPacket.getObjectID(); + log.display(" objectID: " + objectID); + } catch (BoundException e) { + log.complain("Unable to get objectID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check objectID + if (objectID != 0) { + log.complain("Unexpected objectID of event " + i + " in tested event packet: " + + objectID + " (expected: " + 0 + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Check if given location is equal to the expected one. + */ + void checkLocation(JDWP.Location location, JDWP.Location expectedLocation, + int eventNumber, int expectedLine) { + if (location.getTag() != expectedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + + eventNumber + " in tested event packet: " + location.getTag() + + " (expected: " + expectedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != expectedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + + eventNumber + " in tested event packet: " + location.getClassID() + + " (expected: " + expectedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != expectedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + + eventNumber + " in tested event packet: " + location.getMethodID() + + " (expected: " + expectedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != expectedLocation.getIndex()) { +/* + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + expectedLocation.getIndex() + ")"); + success = false; +*/ + try { + // find approximate line number for location + int lineNumber = debugee.getLineNumber(location, true); + if (lineNumber != expectedLine) { + log.complain("Unexpected line number of location of event " + + eventNumber + " in tested event packet: " + lineNumber + + " (expected: " + expectedLine + ")"); + success = false; + } else { + log.display("Unexpected codeIndex of location: " + location.getIndex() + + " (expected: " + expectedLocation.getIndex() + ")"); + log.display("Though line number of catch location is as expected: " + + expectedLine); + } + } catch (Failure e) { + log.complain("Unable to get line number for location of event " + + eventNumber + " in tested event packet:\n\t" + e.getMessage()); + success = false; + } + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/FIELD_ACCESS/fldaccess001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: FIELD_ACCESS + * Test checks that + * 1) debuggee successfully creates FIELD_ACCESS event request + * for particular static filed + * 2) expected FIELD_ACCESS event is received when the thread + * accesses tested field into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: fldaccess001 + * debuggee: fldaccess001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and obtains fieldID + * for tested static field and expected location of FIELD_ACCESS event. + * Then debugger waits for breakpoint is reached by a thread in + * debuggee makes request for FIELD_ACCESS event for known classID and + * fieldID. + * When event is received debugger checks if the received event is for + * expected request, class, thread, field and location, and has correct + * attributes. Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.FIELD_ACCESS.fldaccess001 + * nsk.jdwp.Event.FIELD_ACCESS.fldaccess001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.FIELD_ACCESS.fldaccess001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.FIELD_ACCESS; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class fldaccess001a { + + static final int BREAKPOINT_LINE = 114; + static final int FIELD_ACCESS_LINE = 125; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + fldaccess001a _fldaccess001a = new fldaccess001a(); + System.exit(fldaccess001.JCK_STATUS_BASE + _fldaccess001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread and object + log.display("Creating object of the tested class"); + TestedObjectClass.object = new TestedObjectClass(); + log.display(" ... object created"); + + log.display("Creating tested thread"); + TestedThreadClass thread = new TestedThreadClass(fldaccess001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return fldaccess001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return fldaccess001.PASSED; + } + + // tested thread class + public static class TestedThreadClass extends Thread { + + public TestedThreadClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + // invoke method of tested object class + TestedObjectClass.run(); + + log.display("Tested thread: finished"); + } + } + + // tested object class + public static class TestedObjectClass { + + // static field with object been accessed + public static volatile TestedObjectClass object = null; + + // static field been accessed + public static int value = 0; + + // reach breakpoint and then touch field + public static void run() { + log.display("Breakpoint line reached"); + // next line is location of BREAKPOINT event + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + + // invoke method which accesses the field + methodForAccess(); + } + + // access the tested field + public static void methodForAccess() { + log.display("Before tested field accessed"); + // next line is location of FIELD_ACCESS event + int foo = value; // FIELD_ACCESS_LINE + log.display("After tested field accessed"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.FIELD_MODIFICATION; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: FIELD_MODIFICATION. + * + * See fldmodification001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class fldmodification001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_WATCH_FIELD_MODIFICATION; + static final String VM_CAPABILITY_NAME = "canWatchFieldModification"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.FIELD_MODIFICATION"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "fldmodification001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.FIELD_MODIFICATION; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String OBJECT_FIELD_NAME = "object"; + static final String VALUE_FIELD_NAME = "value"; + static final String TESTED_METHOD_NAME = "methodForAccess"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = fldmodification001a.BREAKPOINT_LINE; + static final int FIELD_MODIFICATION_LINE = fldmodification001a.FIELD_MODIFICATION_LINE; + static final int FIELD_MODIFICATION_VALUE = 6574; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + long testedFieldID = 0; + long testedObjectID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new fldmodification001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // check for VM capability + log.display("\n>>> Checking VM capability \n"); + log.display("Getting VM capability: " + VM_CAPABILITY_NAME); + boolean capable = debugee.getCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME); + log.display(" ... got VM capability: " + capable); + + // exit as PASSED if this capability is not supported + if (!capable) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for FIELD_MODIFICATION event for field: " + + VALUE_FIELD_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested FIELD_MODIFICATION event + log.display("Waiting for FIELD_MODIFICATION event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for FIELD_MODIFICATION event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded:\n\t" + TESTED_CLASS_NAME); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... class loaded with classID: " + testedClassID); + log.display(""); + + // get fieldID for the tested field + log.display("Getting tested fieldID for field name: " + VALUE_FIELD_NAME); + testedFieldID = debugee.getClassFieldID(testedClassID, VALUE_FIELD_NAME, true); + log.display(" ... got fieldID: " + testedFieldID); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for field access line + log.display("Getting codeIndex for field modification line: " + FIELD_MODIFICATION_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, FIELD_MODIFICATION_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location for field modofication line"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + + // get objectID of the tested object from static field + log.display("Getting tested objectID from static field: " + OBJECT_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + testedObjectID = ((Long)value.getValue()).longValue(); + log.display(" ... got objectID: " + testedObjectID); + } + + /** + * Make request for tested FIELD_MODIFICATION event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.FIELD_ONLY + " (FIELD_ONLY)"); + command.addByte(JDWP.EventModifierKind.FIELD_ONLY); + log.display(" classID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + log.display(" fieldID: " + testedFieldID); + command.addFieldID(testedFieldID); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested FIELD_MODIFICATION event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested FIELD_MODIFICATION event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.FIELD_MODIFICATION + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.FIELD_MODIFICATION) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.FIELD_MODIFICATION + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + checkLocation(location, testedLocation, i, FIELD_MODIFICATION_LINE); + + // get type tag + byte refTypeTag = 0; + try { + refTypeTag = eventPacket.getByte(); + log.display(" refTypeTag: " + refTypeTag); + } catch (BoundException e) { + log.complain("Unable to get reftypetag of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check type tag + if (refTypeTag != JDWP.TypeTag.CLASS) { + log.complain("Unexpected refTypeTag of event " + i + " in tested event packet: " + + refTypeTag + " (expected: " + JDWP.TypeTag.CLASS + ")"); + success = false; + } + + // get typeID + long typeID = 0; + try { + typeID = eventPacket.getReferenceTypeID(); + log.display(" typeID: " + typeID); + } catch (BoundException e) { + log.complain("Unable to get typeID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check typeID + if (typeID != testedClassID) { + log.complain("Unexpected typeID of event " + i + " in tested event packet: " + + typeID + " (expected: " + testedClassID + ")"); + success = false; + } + + // get fieldID + long fieldID = 0; + try { + fieldID = eventPacket.getFieldID(); + log.display(" fieldID: " + fieldID); + } catch (BoundException e) { + log.complain("Unable to get fieldID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check fieldID + if (fieldID != testedFieldID) { + log.complain("Unexpected fieldID of event " + i + " in tested event packet: " + + fieldID + " (expected: " + testedFieldID + ")"); + success = false; + } + + // get object tag + byte objectTag = 0; + try { + objectTag = eventPacket.getByte(); + log.display(" objectTag: " + objectTag); + } catch (BoundException e) { + log.complain("Unable to get object tag of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check object tag + if (objectTag != JDWP.Tag.OBJECT) { + log.complain("Unexpected object tag of event " + i + " in tested event packet: " + + objectTag + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // get objectID + long objectID = 0; + try { + objectID = eventPacket.getObjectID(); + log.display(" objectID: " + objectID); + } catch (BoundException e) { + log.complain("Unable to get objectID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check objectID + if (objectID != 0) { + log.complain("Unexpected objectID of event " + i + " in tested event packet: " + + objectID + " (expected: " + 0 + ")"); + success = false; + } + + // get valueToBe + JDWP.Value valueToBe = null; + try { + valueToBe = eventPacket.getValue(); + log.display(" valueToBe: " + valueToBe); + } catch (BoundException e) { + log.complain("Unable to get valueToBe of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check value tag + byte valueTag = valueToBe.getTag(); + if (valueTag != JDWP.Tag.INT) { + log.complain("Unexpected valueToBe tag of event " + i + " in tested event packet: " + + valueTag + " (expected: " + JDWP.Tag.INT + ")"); + success = false; + } + + // check integer value + int intValue = ((Integer)valueToBe.getValue()).intValue(); + if (intValue != FIELD_MODIFICATION_VALUE) { + log.complain("Unexpected valueToBe of event " + i + " in tested event packet: " + + intValue + " (expected: " + FIELD_MODIFICATION_VALUE + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Check if given location is equal to the expected one. + */ + void checkLocation(JDWP.Location location, JDWP.Location expectedLocation, + int eventNumber, int expectedLine) { + if (location.getTag() != expectedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + + eventNumber + " in tested event packet: " + location.getTag() + + " (expected: " + expectedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != expectedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + + eventNumber + " in tested event packet: " + location.getClassID() + + " (expected: " + expectedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != expectedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + + eventNumber + " in tested event packet: " + location.getMethodID() + + " (expected: " + expectedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != expectedLocation.getIndex()) { +/* + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + expectedLocation.getIndex() + ")"); + success = false; +*/ + try { + // find approximate line number for location + int lineNumber = debugee.getLineNumber(location, true); + if (lineNumber != expectedLine) { + log.complain("Unexpected line number of location of event " + + eventNumber + " in tested event packet: " + lineNumber + + " (expected: " + expectedLine + ")"); + success = false; + } else { + log.display("Unexpected codeIndex of location: " + location.getIndex() + + " (expected: " + expectedLocation.getIndex() + ")"); + log.display("Though line number of catch location is as expected: " + + expectedLine); + } + } catch (Failure e) { + log.complain("Unable to get line number for location of event " + + eventNumber + " in tested event packet:\n\t" + e.getMessage()); + success = false; + } + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: FIELD_MODIFICATION + * Test checks that + * 1) debuggee successfully creates FIELD_MODIFICATION event request + * for particular static filed + * 2) expected FIELD_MODIFICATION event is received when the thread + * modifies tested field into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: fldmodification001 + * debuggee: fldmodification001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and obtains fieldID + * for tested static field and expected location of FIELD_MODIFICATION + * event. Then debugger waits for breakpoint is reached by a thread in + * debuggee makes request for FIELD_MODIFICATION event for known + * classID and fieldID. + * When event is received debugger checks if the received event is for + * expected request, class, thread, field and location, and has correct + * value to be assigned and ather attributes. Then debugger removes + * event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.FIELD_MODIFICATION.fldmodification001 + * nsk.jdwp.Event.FIELD_MODIFICATION.fldmodification001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.FIELD_MODIFICATION.fldmodification001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.FIELD_MODIFICATION; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class fldmodification001a { + + static final int BREAKPOINT_LINE = 114; + static final int FIELD_MODIFICATION_LINE = 126; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + fldmodification001a _fldmodification001a = new fldmodification001a(); + System.exit(fldmodification001.JCK_STATUS_BASE + _fldmodification001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread and object + log.display("Creating object of the tested class"); + TestedObjectClass.object = new TestedObjectClass(); + log.display(" ... object created"); + + log.display("Creating tested thread"); + TestedThreadClass thread = new TestedThreadClass(fldmodification001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return fldmodification001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return fldmodification001.PASSED; + } + + // tested thread class + public static class TestedThreadClass extends Thread { + + public TestedThreadClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + // invoke method of tested object class + TestedObjectClass.run(); + + log.display("Tested thread: finished"); + } + } + + // tested object class + public static class TestedObjectClass { + + // static field with object been accessed + public static volatile TestedObjectClass object = null; + + // static field been accessed + public static int value = 0; + + // reach breakpoint and then touch field + public static void run() { + log.display("Breakpoint line reached"); + // next line is location of BREAKPOINT event + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + + // invoke method which accesses the field + methodForAccess(); + } + + // access the tested field + public static void methodForAccess() { + log.display("Assigning to tested field new value: " + + fldmodification001.FIELD_MODIFICATION_VALUE); + // next line is location of FIELD_MODIFICATION event + value = fldmodification001.FIELD_MODIFICATION_VALUE; // FIELD_MODIFICATION_LINE + log.display("Tested field modified"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,640 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.METHOD_ENTRY; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: METHOD_ENTRY. + * + * See methentry001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class methentry001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.METHOD_ENTRY"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "methentry001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.METHOD_ENTRY; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String TESTED_METHOD_NAME = "testedMethod"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = methentry001a.BREAKPOINT_LINE; + static final int METHOD_ENTRY_LINE = methentry001a.METHOD_ENTRY_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new methentry001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for METHOD_ENTRY event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested METHOD_ENTRY event + log.display("Waiting for METHOD_ENTRY event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for METHOD_ENTRY event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for method entry line + log.display("Getting codeIndex for method entry line: " + METHOD_ENTRY_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, METHOD_ENTRY_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location for method entry"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + } + + /** + * Make request for tested METHOD_ENTRY event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.CLASS_ONLY); + command.addByte(JDWP.EventModifierKind.CLASS_ONLY); + log.display(" classID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested METHOD_ENTRY event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested METHOD_ENTRY event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.METHOD_ENTRY + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.METHOD_ENTRY) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.METHOD_ENTRY + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + if (location.getTag() != testedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + i + + " in tested event packet: " + location.getTag() + + " (expected: " + testedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != testedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + i + + " in tested event packet: " + location.getClassID() + + " (expected: " + testedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != testedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + i + + " in tested event packet: " + location.getMethodID() + + " (expected: " + testedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != testedLocation.getIndex()) { + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + testedLocation.getIndex() + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/METHOD_ENTRY/methentry001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: METHOD_ENTRY + * Test checks that + * 1) debuggee successfully creates METHOD_ENTRY event request + * for particular classID + * 2) expected METHOD_ENTRY event is received when the thread + * entered tested method into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: methentry001 + * debuggee: methentry001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and breakpoint reached. + * Then debugger gets methodID and entry location for tested method and + * makes request for METHOD_ENTRY event of methods of this class. + * When event is received debugger checks if the received event is for + * expected class, thread, method and location and has correct attributes. + * Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.METHOD_ENTRY.methentry001 + * nsk.jdwp.Event.METHOD_ENTRY.methentry001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.METHOD_ENTRY.methentry001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.METHOD_ENTRY; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class methentry001a { + + static final int BREAKPOINT_LINE = 91; + static final int METHOD_ENTRY_LINE = 103; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + methentry001a _methentry001a = new methentry001a(); + System.exit(methentry001.JCK_STATUS_BASE + _methentry001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass thread = new TestedClass(methentry001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return methentry001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return methentry001.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + + log.display("Invoking tested method"); + testedMethod(); + log.display("Tested method invoked"); + + log.display("Tested thread: finished"); + } + + public static void testedMethod() { + // next line is for method entry location + log.display("Tested method entered"); // METHOD_ENTRY_LINE + log.display("Tested method exited"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,640 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.METHOD_EXIT; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: METHOD_EXIT. + * + * See methexit001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class methexit001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.METHOD_EXIT"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "methexit001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.METHOD_EXIT; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String TESTED_METHOD_NAME = "testedMethod"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = methexit001a.BREAKPOINT_LINE; + static final int METHOD_EXIT_LINE = methexit001a.METHOD_EXIT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new methexit001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for METHOD_EXIT event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested METHOD_EXIT event + log.display("Waiting for METHOD_EXIT event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for METHOD_EXIT event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for method entry line + log.display("Getting codeIndex for method exit line: " + METHOD_EXIT_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, METHOD_EXIT_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location for method exit"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + } + + /** + * Make request for tested METHOD_EXIT event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.CLASS_ONLY); + command.addByte(JDWP.EventModifierKind.CLASS_ONLY); + log.display(" classID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested METHOD_EXIT event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested METHOD_EXIT event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.METHOD_EXIT + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.METHOD_EXIT) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.METHOD_EXIT + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + if (location.getTag() != testedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + i + + " in tested event packet: " + location.getTag() + + " (expected: " + testedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != testedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + i + + " in tested event packet: " + location.getClassID() + + " (expected: " + testedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != testedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + i + + " in tested event packet: " + location.getMethodID() + + " (expected: " + testedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != testedLocation.getIndex()) { + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + testedLocation.getIndex() + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/METHOD_EXIT/methexit001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: METHOD_EXIT + * Test checks that + * 1) debuggee successfully creates METHOD_EXIT event request + * for particular classID + * 2) expected METHOD_EXIT event is received when the thread + * exited tested method into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: methexit001 + * debuggee: methexit001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and breakpoint reached. + * Then debugger gets methodID and method exit location for tested method + * and makes request for METHOD_EXIT event of methods of this class. + * When event is received debugger checks if the received event is for + * expected class, thread, method and location and has correct attributes. + * Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.METHOD_EXIT.methexit001 + * nsk.jdwp.Event.METHOD_EXIT.methexit001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.METHOD_EXIT.methexit001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.METHOD_EXIT; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class methexit001a { + + static final int BREAKPOINT_LINE = 91; + static final int METHOD_EXIT_LINE = 105; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + methexit001a _methexit001a = new methexit001a(); + System.exit(methexit001.JCK_STATUS_BASE + _methexit001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass thread = new TestedClass(methexit001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return methexit001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return methexit001.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + + log.display("Invoking tested method"); + testedMethod(); + log.display("Tested method invoked"); + + log.display("Tested thread: finished"); + } + + public static void testedMethod() { + log.display("Tested method entered"); + log.display("Tested method exited"); + // next line is for method exit location + return; // METHOD_EXIT_LINE + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,645 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.SINGLE_STEP; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: SINGLE_STEP. + * + * See singlestep001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class singlestep001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.SINGLE_STEP"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "singlestep001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.SINGLE_STEP; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + static final int STEP_DEPTH = JDWP.StepDepth.OVER; + static final int STEP_SIZE = JDWP.StepSize.LINE; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = singlestep001a.BREAKPOINT_LINE; + static final int SINGLE_STEP_LINE = singlestep001a.SINGLE_STEP_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new singlestep001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for SINGLE_STEP event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested SINGLE_STEP event + log.display("Waiting for SINGLE_STEP event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for SINGLE_STEP event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + BREAKPOINT_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, BREAKPOINT_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for method entry line + log.display("Getting codeIndex for single step line: " + SINGLE_STEP_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, SINGLE_STEP_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location of single step event"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + } + + /** + * Make request for tested SINGLE_STEP event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.STEP + " (STEP)"); + command.addByte(JDWP.EventModifierKind.STEP); + log.display(" threadID: " + testedThreadID); + command.addObjectID(testedThreadID); + log.display(" size: " + STEP_SIZE); + command.addInt(STEP_SIZE); + log.display(" depth: " + STEP_DEPTH); + command.addInt(STEP_DEPTH); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested SINGLE_STEP event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested SINGLE_STEP event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.SINGLE_STEP) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + if (location.getTag() != testedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + i + + " in tested event packet: " + location.getTag() + + " (expected: " + testedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != testedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + i + + " in tested event packet: " + location.getClassID() + + " (expected: " + testedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != testedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + i + + " in tested event packet: " + location.getMethodID() + + " (expected: " + testedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != testedLocation.getIndex()) { + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + testedLocation.getIndex() + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/SINGLE_STEP/singlestep001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: SINGLE_STEP + * Test checks that + * 1) debuggee successfully creates SINGLE_STEP event request + * for particular threadID with attributes: + * depth=OVER, size=LINE + * 2) expected SINGLE_STEP event is received when the thread + * in debuggee steps to the next line after breakpoint + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: singlestep001 + * debuggee: singlestep001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and gets methodID + * and location for expected single step event after breakpoint. + * Then debugger waits for breakpoint reached with some thread + * and makes request for SINGLE_STEP event for this threadID. + * When event is received debugger checks if the received event is for + * expected request, thread, and location and has correct attributes. + * Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.SINGLE_STEP.singlestep001 + * nsk.jdwp.Event.SINGLE_STEP.singlestep001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.SINGLE_STEP.singlestep001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.SINGLE_STEP; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class singlestep001a { + + static final int BREAKPOINT_LINE = 91; + static final int SINGLE_STEP_LINE = 94; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + singlestep001a _singlestep001a = new singlestep001a(); + System.exit(singlestep001.JCK_STATUS_BASE + _singlestep001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass thread = new TestedClass(singlestep001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return singlestep001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return singlestep001.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + + // next line is for SINGLE_STEP event + foo = 10; // SINGLE_STEP_LINE + + log.display("Tested thread: finished"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.SINGLE_STEP; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: SINGLE_STEP. + * + * See singlestep002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class singlestep002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.SINGLE_STEP"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "singlestep002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.SINGLE_STEP; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + static final int STEP_DEPTH = JDWP.StepDepth.INTO; + static final int STEP_SIZE = JDWP.StepSize.LINE; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final String STEP_METHOD_NAME = "methodForStep"; + static final int BREAKPOINT_LINE = singlestep002a.BREAKPOINT_LINE; + static final int SINGLE_STEP_LINE = singlestep002a.SINGLE_STEP_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + long stepMethodID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new singlestep002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for SINGLE_STEP event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested SINGLE_STEP event + log.display("Waiting for SINGLE_STEP event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for SINGLE_STEP event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + BREAKPOINT_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, BREAKPOINT_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get methodID for the method with STEP_EVENT + log.display("Getting methodID for STEP_EVENT method name: " + STEP_METHOD_NAME); + stepMethodID = debugee.getMethodID(testedClassID, STEP_METHOD_NAME, true); + log.display(" ... got methodID: " + stepMethodID); + + // get codeIndex for method entry line + log.display("Getting codeIndex for single step line: " + SINGLE_STEP_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, stepMethodID, SINGLE_STEP_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location of single step event"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + stepMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + } + + /** + * Make request for tested SINGLE_STEP event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.STEP + " (STEP)"); + command.addByte(JDWP.EventModifierKind.STEP); + log.display(" threadID: " + testedThreadID); + command.addObjectID(testedThreadID); + log.display(" size: " + STEP_SIZE); + command.addInt(STEP_SIZE); + log.display(" depth: " + STEP_DEPTH); + command.addInt(STEP_DEPTH); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested SINGLE_STEP event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested SINGLE_STEP event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.SINGLE_STEP) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + if (location.getTag() != testedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + i + + " in tested event packet: " + location.getTag() + + " (expected: " + testedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != testedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + i + + " in tested event packet: " + location.getClassID() + + " (expected: " + testedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != testedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + i + + " in tested event packet: " + location.getMethodID() + + " (expected: " + testedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != testedLocation.getIndex()) { + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + testedLocation.getIndex() + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/SINGLE_STEP/singlestep002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: SINGLE_STEP + * Test checks that + * 1) debuggee successfully creates SINGLE_STEP event request + * for particular threadID with attributes: + * depth=INTO, size=LINE + * 2) expected SINGLE_STEP event is received when the thread + * in debuggee steps to the next line after breakpoint + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: singlestep002 + * debuggee: singlestep002a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and gets methodID + * and location for expected single step event into invoked method. + * Then debugger waits for breakpoint reached with some thread + * and makes request for SINGLE_STEP event for this threadID. + * When event is received debugger checks if the received event is for + * expected request, thread, and location and has correct attributes. + * Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.SINGLE_STEP.singlestep002 + * nsk.jdwp.Event.SINGLE_STEP.singlestep002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.SINGLE_STEP.singlestep002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.SINGLE_STEP; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class singlestep002a { + + static final int BREAKPOINT_LINE = 91; + static final int SINGLE_STEP_LINE = 101; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + singlestep002a _singlestep002a = new singlestep002a(); + System.exit(singlestep002.JCK_STATUS_BASE + _singlestep002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass thread = new TestedClass(singlestep002.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return singlestep002.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return singlestep002.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + methodForStep(); // BREAKPOINT_LINE + + // next line should be reached after step request removed + int foo = 0; + + log.display("Tested thread: finished"); + } + + public void methodForStep() { + // next line is for SINGLE_STEP event + int foo = 100; // SINGLE_STEP_LINE + log.display("Method for step event entered"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.SINGLE_STEP; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: SINGLE_STEP. + * + * See singlestep003.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class singlestep003 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.SINGLE_STEP"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "singlestep003"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.SINGLE_STEP; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + static final int STEP_DEPTH = JDWP.StepDepth.OUT; + static final int STEP_SIZE = JDWP.StepSize.LINE; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String BREAKPOINT_METHOD_NAME = "methodForBreakpoint"; + static final String STEP_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = singlestep003a.BREAKPOINT_LINE; + static final int SINGLE_STEP_LINE = singlestep003a.SINGLE_STEP_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + long stepMethodID = 0; + JDWP.Location testedLocation = null; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new singlestep003().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for SINGLE_STEP event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested SINGLE_STEP event + log.display("Waiting for SINGLE_STEP event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for SINGLE_STEP event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for the tested method + log.display("Getting tested methodID for method name: " + BREAKPOINT_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, BREAKPOINT_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get methodID for the method with STEP_EVENT + log.display("Getting methodID for STEP_EVENT method name: " + STEP_METHOD_NAME); + stepMethodID = debugee.getMethodID(testedClassID, STEP_METHOD_NAME, true); + log.display(" ... got methodID: " + stepMethodID); + + // get codeIndex for method entry line + log.display("Getting codeIndex for single step line: " + SINGLE_STEP_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, stepMethodID, SINGLE_STEP_LINE); + log.display(" ... got index: " + codeIndex); + + // create location for method entry line + log.display("Creating location of single step event"); + testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + stepMethodID, codeIndex); + log.display(" ... got location: " + testedLocation); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + testedThreadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + log.display(""); + } + + /** + * Make request for tested SINGLE_STEP event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.STEP + " (STEP)"); + command.addByte(JDWP.EventModifierKind.STEP); + log.display(" threadID: " + testedThreadID); + command.addObjectID(testedThreadID); + log.display(" size: " + STEP_SIZE); + command.addInt(STEP_SIZE); + log.display(" depth: " + STEP_DEPTH); + command.addInt(STEP_DEPTH); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested SINGLE_STEP event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested SINGLE_STEP event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.SINGLE_STEP) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check location + if (location.getTag() != testedLocation.getTag()) { + log.complain("Unexpected class tag of location of event " + i + + " in tested event packet: " + location.getTag() + + " (expected: " + testedLocation.getTag() + ")"); + success = false; + } + if (location.getClassID() != testedLocation.getClassID()) { + log.complain("Unexpected classID of location of event " + i + + " in tested event packet: " + location.getClassID() + + " (expected: " + testedLocation.getClassID() + ")"); + success = false; + } + if (location.getMethodID() != testedLocation.getMethodID()) { + log.complain("Unexpected methodID of location of event " + i + + " in tested event packet: " + location.getMethodID() + + " (expected: " + testedLocation.getMethodID() + ")"); + success = false; + } + if (location.getIndex() != testedLocation.getIndex()) { + log.complain("Unexpected codeIndex of location of event " + i + + " in tested event packet: " + location.getIndex() + + " (expected: " + testedLocation.getIndex() + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/SINGLE_STEP/singlestep003. + * VM Testbase keywords: [quick, jpda, jdwp, exclude] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: SINGLE_STEP + * Test checks that + * 1) debuggee successfully creates SINGLE_STEP event request + * for particular threadID with attributes: + * depth=OUT, size=LINE + * 2) expected SINGLE_STEP event is received when the thread + * in debuggee steps to the next line after breakpoint + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: singlestep003 + * debuggee: singlestep003a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and gets methodID + * and location for expected single step event out of invoked method. + * Then debugger waits for breakpoint reached with some thread + * and makes request for SINGLE_STEP event for this threadID. + * When event is received debugger checks if the received event is for + * expected request, thread, and location and has correct attributes. + * Then debugger removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.SINGLE_STEP.singlestep003 + * nsk.jdwp.Event.SINGLE_STEP.singlestep003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.SINGLE_STEP.singlestep003 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.SINGLE_STEP; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class singlestep003a { + + static final int BREAKPOINT_LINE = 101; + static final int SINGLE_STEP_LINE = 92; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + singlestep003a _singlestep003a = new singlestep003a(); + System.exit(singlestep003.JCK_STATUS_BASE + _singlestep003a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass thread = new TestedClass(singlestep003.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return singlestep003.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return singlestep003.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread: started"); + + log.display("Invoking tested method"); + methodForBreakpoint(); + // next line is for out step event + int foo = 0; // SINGLE_STEP_LINE + log.display(" ... tested method invoked"); + + log.display("Tested thread: finished"); + } + + public void methodForBreakpoint() { + log.display("Breakpoint line reached"); + // next line is for breakpoint before out step event request + int foo = 100; // BREAKPOINT_LINE + foo = foo + 100; + foo = foo + 100; + foo = foo + 100; + foo = foo + 100; + log.display("Returned from tested method"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,588 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.THREAD_DEATH; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: THREAD_DEATH. + * + * See thrdeath001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class thrdeath001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.THREAD_DEATH"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "thrdeath001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.THREAD_DEATH; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String BREAKPOINT_METHOD_NAME = "ready"; + static final int BREAKPOINT_LINE = thrdeath001a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new thrdeath001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for THREAD_DEATH event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested THREAD_DEATH event + log.display("Waiting for THREAD_DEATH event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for THREAD_DEATH event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + long threadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + threadID); + log.display(""); + + // get thread value from static field of tested class + log.display("Getting thread value from static field: " + THREAD_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, THREAD_FIELD_NAME, + JDWP.Tag.THREAD); + testedThreadID = ((Long)value.getValue()).longValue(); + log.display(" ... got threadID: " + testedThreadID); + } + + /** + * Make request for tested THREAD_DEATH event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.THREAD_ONLY); + command.addByte(JDWP.EventModifierKind.THREAD_ONLY); + log.display(" threadID: " + testedThreadID); + command.addObjectID(testedThreadID); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested THREAD_DEATH event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested THREAD_DEATH event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.THREAD_DEATH + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.THREAD_DEATH) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.THREAD_DEATH + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/THREAD_DEATH/thrdeath001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: THREAD_DEATH + * Test checks that + * 1) debuggee successfully creates THREAD_DEATH event request + * for particular threadID + * 2) expected THREAD_DEATH event is received when the thread + * finished into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: thrdeath001 + * debuggee: thrdeath001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and breakpoint reached. + * Then debugger gets threadID from the class static field and makes + * THREAD_DEATH event request for this thread, + * When event is received debugger checks if the received event + * is for this thread and has correct attributes. Then debugger + * removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.THREAD_DEATH.thrdeath001 + * nsk.jdwp.Event.THREAD_DEATH.thrdeath001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.THREAD_DEATH.thrdeath001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.THREAD_DEATH; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class thrdeath001a { + + static final int BREAKPOINT_LINE = 93; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + thrdeath001a _thrdeath001a = new thrdeath001a(); + System.exit(thrdeath001.JCK_STATUS_BASE + _thrdeath001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass.thread = new TestedClass(thrdeath001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // reach breakpoint + TestedClass.ready(); + + // start tested thread + log.display("Starting tested thread"); + TestedClass.thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + TestedClass.thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return thrdeath001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return thrdeath001.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public static volatile TestedClass thread = null; + + public TestedClass(String name) { + super(name); + } + + public static void ready() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + + public void run() { + log.display("Tested thread: started"); + log.display("Tested thread: finished"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,588 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.THREAD_START; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: THREAD_START. + * + * See thrstart001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class thrstart001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.THREAD_START"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "thrstart001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.THREAD_START; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_THREAD_NAME = "TestedThread"; + + // name of field and method of tested class + static final String THREAD_FIELD_NAME = "thread"; + static final String BREAKPOINT_METHOD_NAME = "ready"; + static final int BREAKPOINT_LINE = thrstart001a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedThreadID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new thrstart001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // prepare debuggee + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for THREAD_START event for class:\n\t" + + TESTED_CLASS_NAME); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested THREAD_START event + log.display("Waiting for THREAD_START event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + // clear tested request for THREAD_START event + log.display("Clearing request for tested event"); + clearTestedRequest(); + log.display(" ... request removed"); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); + long threadID = debugee.waitForBreakpointReached(testedClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + threadID); + log.display(""); + + // get thread value from static field of tested class + log.display("Getting thread value from static field: " + THREAD_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, THREAD_FIELD_NAME, + JDWP.Tag.THREAD); + testedThreadID = ((Long)value.getValue()).longValue(); + log.display(" ... got threadID: " + testedThreadID); + } + + /** + * Make request for tested THREAD_START event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + JDWP.EventModifierKind.THREAD_ONLY); + command.addByte(JDWP.EventModifierKind.THREAD_ONLY); + log.display(" threadID: " + testedThreadID); + command.addObjectID(testedThreadID); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Clear request for tested THREAD_START event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested THREAD_START event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.THREAD_START + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.THREAD_START) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.THREAD_START + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID != testedThreadID) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + threadID + " (expected: " + testedThreadID + ")"); + success = false; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/THREAD_START/thrstart001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * command set: EventRequest + * command: Set, Clear + * event kind: THREAD_START + * Test checks that + * 1) debuggee successfully creates THREAD_START event request + * for particular threadID + * 2) expected THREAD_START event is received when the thread + * started into debuggee + * 3) debuggee successfully removes event request + * Test consists of two compoments: + * debugger: thrstart001 + * debuggee: thrstart001a + * First, debugger uses nsk.share support classes to launch debuggee, + * and obtains Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and breakpoint reached. + * Then debugger gets threadID from the class static field and makes + * THREAD_START event request for this thread, + * When event is received debugger checks if the received event + * is for this thread and has correct attributes. Then debugger + * removes event request. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.THREAD_START.thrstart001 + * nsk.jdwp.Event.THREAD_START.thrstart001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.THREAD_START.thrstart001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Event.THREAD_START; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class thrstart001a { + + static final int BREAKPOINT_LINE = 93; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + thrstart001a _thrstart001a = new thrstart001a(); + System.exit(thrstart001.JCK_STATUS_BASE + _thrstart001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating tested thread"); + TestedClass.thread = new TestedClass(thrstart001.TESTED_THREAD_NAME); + log.display(" ... thread created"); + + // reach breakpoint + TestedClass.ready(); + + // start tested thread + log.display("Starting tested thread"); + TestedClass.thread.start(); + log.display(" ... thread started"); + + // wait for thread finished + try { + log.display("Waiting for tested thread finished"); + TestedClass.thread.join(); + log.display(" ... thread finished"); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished"); + return thrstart001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return thrstart001.PASSED; + } + + // tested class + public static class TestedClass extends Thread { + public static volatile TestedClass thread = null; + + public TestedClass(String name) { + super(name); + } + + public static void ready() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + + public void run() { + log.display("Tested thread: started"); + log.display("Tested thread: finished"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.VM_DEATH; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: VM_DEATH. + * + * See vmdeath001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class vmdeath001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.VM_DEATH"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "vmdeath001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Event.Composite"; + static final int JDWP_COMMAND_ID = JDWP.Command.Event.Composite; + static final int JDWP_EVENT_KIND = JDWP.EventKind.VM_DEATH; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new vmdeath001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for tested VM_DEATH event + log.display("\n>>> Testing JDWP event \n"); + waitForTestedEvent(); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Wait for tested VM_DEATH event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet (for " + timeout + "ms timeout)"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is OK"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != JDWP.SuspendPolicy.NONE) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + JDWP.SuspendPolicy.NONE + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind != JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + return; + } + dead = true; + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != 0) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + 0 + ")"); + success = false; + return; + } + + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/VM_DEATH/vmdeath001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * event kind: VM_DEATH + * Test checks that debugee accept the event packet with correct + * attributes at debuggee's exit. + * Test consists of two compoments: + * debugger: vmdeath001 + * debuggee: vmdeath001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Debugger waits for debuggee started and resumes it to allow debuggee + * to exit. + * Next, debugger waits for an event packet and check if the received + * event is a single VM_DEATH event with correct attributes. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.VM_DEATH.vmdeath001 + * nsk.jdwp.Event.VM_DEATH.vmdeath001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.VM_DEATH.vmdeath001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.VM_DEATH; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class vmdeath001a { + + public static void main(String args[]) { + vmdeath001a _vmdeath001a = new vmdeath001a(); + System.exit(vmdeath001.JCK_STATUS_BASE + _vmdeath001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // exit debugee + log.display("Debugee PASSED"); + return vmdeath001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.VM_DEATH; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: VM_DEATH. + * + * See vmdeath002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class vmdeath002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // VM capability constants + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_REQUEST_VMDEATH_EVENT; + static final String VM_CAPABILITY_NAME = "canRequestVMDeathEvent"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.VM_DEATH"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "vmdeath002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP event constants + static final byte TESTED_EVENT_KIND = JDWP.EventKind.VM_DEATH; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean resumed = false; + boolean success = true; + + // obtained data + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new vmdeath002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // check for VM capability + log.display("\n>>> Checking VM capability \n"); + log.display("Getting VM capability: " + VM_CAPABILITY_NAME); + boolean capable = debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME); + log.display(" ... got VM capability: " + capable); + + // exit as PASSED if this capability is not supported + if (!capable) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // test JDWP event + log.display("\n>>> Testing JDWP event \n"); + log.display("Making request for METHOD_DEATH event"); + requestTestedEvent(); + log.display(" ... got requestID: " + eventRequestID); + log.display(""); + + // resume debuggee + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for tested VM_DEATH event + log.display("Waiting for VM_DEATH event received"); + waitForTestedEvent(); + log.display(" ... event received"); + log.display(""); + + if (!dead) { + // clear tested request for VM_DEATH event + log.display("\n>>> Clearing request for tested event \n"); + clearTestedRequest(); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + } else if (!resumed) { + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Make request for tested METHOD_ENTRY event. + */ + void requestTestedEvent() { + Failure failure = new Failure("Error occured while makind request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Set"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + log.display(" eventKind: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 0); + command.addInt(0); + command.setLength(); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + throw failure; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + throw failure; + } + + eventRequestID = requestID; + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + + } + + /** + * Clear request for tested METHOD_ENTRY event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + log.display(""); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + log.display(""); + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested VM_DEATH event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is OK"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + int eventReceived = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind != TESTED_EVENT_KIND) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + TESTED_EVENT_KIND + ")"); + success = false; + continue; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + dead = true; + resumed = (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY); + return; + } + + // check requestID + if (requestID == eventRequestID) { + eventReceived++; + } else if (requestID == 0) { + dead = true; + resumed = (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY); + } else { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + " or 0)"); + success = false; + return; + } + + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + int extra = eventPacket.length() - eventPacket.currentPosition(); + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString() + " (" + extra + " bytes)"); + success = false; + } + + log.display(" ... event packet parsed"); + + if (eventReceived <= 0) { + log.complain("No requested event received: " + eventReceived + " (expected: 1)"); + success = false; + } + + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/VM_DEATH/vmdeath002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * event kind: VM_DEATH + * Test checks that resquested VM_DEATH event is received upon + * debuggee VM exit either together with automatically generated + * VM_DEATH event or in a singleton event packet. + * Test consists of two compoments: + * debugger: vmdeath002 + * debuggee: vmdeath002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Debugger waits for debuggee started and makes an request for VM_DEATH + * event. Then, it resumes debuggee to allow it to exit. + * Next, debugger waits for an event packet and check if the received + * event contains only VM_DEATH events either requested one or automatically + * generated one. Received event should have expected requestID and + * correct attributes. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * Test was fixed due to test bug: + * 4863716 TEST_BUG: misprint in JDWP test vmdeath002 + * Test was fixed due to test bug: + * 4973268 TEST_BUG: nsk/jdwp/Event/VM_DEATH/vmdeath002 needs to be updated + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.VM_DEATH.vmdeath002 + * nsk.jdwp.Event.VM_DEATH.vmdeath002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.VM_DEATH.vmdeath002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.VM_DEATH; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class vmdeath002a { + + public static void main(String args[]) { + vmdeath002a _vmdeath002a = new vmdeath002a(); + System.exit(vmdeath002.JCK_STATUS_BASE + _vmdeath002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // exit debugee + log.display("Debugee PASSED"); + return vmdeath002.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.VM_START; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP event: VM_START. + * + * See vmstart001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP event is tested in the method waitForTestedEvent(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class vmstart001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Event.VM_START"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "vmstart001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Event.Composite"; + static final int JDWP_COMMAND_ID = JDWP.Command.Event.Composite; + static final int JDWP_EVENT_KIND = JDWP.EventKind.VM_START; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new vmstart001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for tested VM_START event + log.display("\n>>> Testing JDWP event \n"); + waitForTestedEvent(); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Wait for tested VM_START event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is OK"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + if (suspendPolicy != JDWP.SuspendPolicy.ALL) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + JDWP.SuspendPolicy.ALL + ")"); + success = false; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + + eventKind + " (expected: " + JDWP.EventKind.THREAD_START + ")"); + dead = true; + success = false; + return; + } else if (eventKind != JDWP.EventKind.VM_START) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_START + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != 0) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + 0 + ")"); + success = false; + return; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (threadID == 0) { + log.complain("Unexpected null threadID of event " + i + " in tested event packet: " + + threadID + " (expected: not " + 0 + ")"); + success = false; + return; + } + + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Event/VM_START/vmstart001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Event + * command: Composite + * event kind: VM_START + * Test checks that debugee accept the event packet with correct + * attributes at debuggee's startup. + * Test consists of two compoments: + * debugger: vmstart001 + * debuggee: vmstart001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for an event packet and check if the received + * event is a single VM_START event with correct attributes. + * Finally, debugger disconnects debuggee, waits for it exited + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Event.VM_START.vmstart001 + * nsk.jdwp.Event.VM_START.vmstart001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Event.VM_START.vmstart001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Event.VM_START; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class vmstart001a { + + public static void main(String args[]) { + vmstart001a _vmstart001a = new vmstart001a(); + System.exit(vmstart001.JCK_STATUS_BASE + _vmstart001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // exit debugee + log.display("Debugee PASSED"); + return vmstart001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.Clear; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: EventRequest.Clear. + * + * See clear001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class clear001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.EventRequest.Clear"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clear001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "EventRequest.Clear"; + static final int JDWP_COMMAND_ID = JDWP.Command.EventRequest.Clear; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.BREAKPOINT; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of field and method of tested class + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = clear001a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedMethodID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new clear001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Get debuggee prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event instead of BREAKPOINT event"); + waitForVMDeathEvent(); + + if (!dead) { + // resume debuggee after BREAKPOINT event + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for final VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for tested method + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // make request for BREAKPOINT event + log.display("Making request for BREAKPOINT event at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + eventRequestID = debugee.requestBreakpointEvent(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... got requestID: " + eventRequestID); + } + + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no out data + log.display(" no out data"); + + log.display(" ... packet data is parsed"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Wait for VM_DEATH event. + */ + void waitForVMDeathEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Expected VM_DEATH event received intead of BREAKPOINT event"); + dead = true; + return; + } else if (eventKind == JDWP.EventKind.BREAKPOINT) { + log.complain("Unexpected BREAKPOINT event received in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + } else { + log.complain("Unexpected eventKind of event " + i + " in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in BREAKPOINT event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/EventRequest/Clear/clear001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: EventRequest + * command: Clear + * event kind: BREAKPOINT + * Test checks that debuggee accept tested command and replies + * with correct reply packet. Also test checks that no breakpoint + * events occurs for cleared BREAKPOINT request. + * Test consists of two compoments: + * debugger: clear001 + * debuggee: clear001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded into debuggee and + * makes request for BREAKPOINT at method run(). + * Then, debugger creates creates command packet for command + * EventRequest.Clear with created requestID, sends it to debuggee, + * waits for reply packet and check that reply is correct and has + * no reply data. + * Then, debugger resumes debuggee and waits for an VM_DEATH event. + * If received event is BREAKPOINT event, debugger complains an error. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.EventRequest.Clear.clear001 + * nsk.jdwp.EventRequest.Clear.clear001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.EventRequest.Clear.clear001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.EventRequest.Clear; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class clear001a { + + static final int BREAKPOINT_LINE = 80; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + clear001a _clear001a = new clear001a(); + System.exit(clear001.JCK_STATUS_BASE + _clear001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass object = new TestedClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + log.display("Invoking method with breakpoint"); + object.run(); + log.display(" ... method invoked"); + + // exit debugee + log.display("Debugee PASSED"); + return clear001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + + public void run() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.ClearAllBreakpoints; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: EventRequest.ClearAllBreakpoints. + * + * See clrallbreakp001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class clrallbreakp001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.EventRequest.ClearAllBreakpoints"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clrallbreakp001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "EventRequest.ClearAllBreakpoints"; + static final int JDWP_COMMAND_ID = JDWP.Command.EventRequest.ClearAllBreakpoints; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.VM_START; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of field and method of tested class + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = clrallbreakp001a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedMethodID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new clrallbreakp001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Get debuggee prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event instead of BREAKPOINT event"); + waitForVMDeathEvent(); + + if (!dead) { + // resume debuggee after BREAKPOINT event + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for fianl VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for tested method + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // make request for BREAKPOINT event + log.display("Making request for BREAKPOINT event at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + eventRequestID = debugee.requestBreakpointEvent(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... got requestID: " + eventRequestID); + } + + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" no out data"); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no out data + log.display(" no out data"); + + log.display(" ... packet data is parsed"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Wait for VM_DEATH event. + */ + void waitForVMDeathEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Expected VM_DEATH event received intead of BREAKPOINT event"); + dead = true; + return; + } else if (eventKind == JDWP.EventKind.BREAKPOINT) { + log.complain("Unexpected BREAKPOINT event received in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + } else { + log.complain("Unexpected eventKind of event " + i + " in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in BREAKPOINT event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: EventRequest + * command: ClearAllBreakpoints + * Test checks that debuggee accept tested command and replies + * with correct reply packet. Also test checks that no breakpoint + * events occures for previously created BREAKPOINT request. + * Test consists of two compoments: + * debugger: clrallbreakp001 + * debuggee: clrallbreakp001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded into debuggee and + * makes request for BREAKPOINT at method run(). + * Then, debugger creates creates command packet for command + * EventRequest.ClearAllBreakpoints, sends it to debuggee, waits + * for reply packet and check that reply is correct and has no reply data. + * Then, debugger resumes debuggee and waits for an VM_DEATH event. + * If received event is BREAKPOINT event, debugger complains an error. + * Finally, debugger disconnectes debuggee, waits for it exits + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp001 + * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.EventRequest.ClearAllBreakpoints; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class clrallbreakp001a { + + static final int BREAKPOINT_LINE = 80; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + clrallbreakp001a _clrallbreakp001a = new clrallbreakp001a(); + System.exit(clrallbreakp001.JCK_STATUS_BASE + _clrallbreakp001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass object = new TestedClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + log.display("Invoking method with breakpoint"); + object.run(); + log.display(" ... method invoked"); + + // exit debugee + log.display("Debugee PASSED"); + return clrallbreakp001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + + public void run() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.ClearAllBreakpoints; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: EventRequest.ClearAllBreakpoints. + * + * See clrallbreakp002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class clrallbreakp002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.EventRequest.ClearAllBreakpoints"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clrallbreakp002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "EventRequest.ClearAllBreakpoints"; + static final int JDWP_COMMAND_ID = JDWP.Command.EventRequest.ClearAllBreakpoints; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.VM_START; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new clrallbreakp002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + } + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" no out data"); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no out data + log.display(" no out data"); + + log.display(" ... packet data is parsed"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: EventRequest + * command: ClearAllBreakpoints + * Test checks that debugee accepts command packet for tested command + * and replies with correct reply packet, even if no requests for + * BREAKPOINT event had been made before. + * Test consists of two compoments: + * debugger: clrallbreakp002 + * debuggee: clrallbreakp002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded, creates command packet + * for EventRequest.ClearAllBreakpoints command and sends it to debuggee. + * Then debugger reads reply packet and checks if reply packet is correct + * and has no reply data. + * Finally, debugger disconnectes debuggee, waits for it exits + * and exits too with proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp002 + * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.ClearAllBreakpoints; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class clrallbreakp002a { + + public static void main(String args[]) { + clrallbreakp002a _clrallbreakp002a = new clrallbreakp002a(); + System.exit(clrallbreakp002.JCK_STATUS_BASE + _clrallbreakp002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display(" ... object created"); + + // exit debugee + log.display("Debugee PASSED"); + return clrallbreakp002.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.ClearAllBreakpoints; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: EventRequest.ClearAllBreakpoints. + * + * See clrallbreakp003.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class clrallbreakp003 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.EventRequest.ClearAllBreakpoints"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clrallbreakp003"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "EventRequest.ClearAllBreakpoints"; + static final int JDWP_COMMAND_ID = JDWP.Command.EventRequest.ClearAllBreakpoints; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.VM_START; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of field and method of tested class + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = clrallbreakp003a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedMethodID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new clrallbreakp003().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Get debuggee prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for fianl VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for tested method + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // make request for BREAKPOINT event + log.display("Making request for BREAKPOINT event at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + eventRequestID = debugee.requestBreakpointEvent(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... got requestID: " + eventRequestID); + + // clear request for BREAKPOINT event + log.display("Clearing BREAKPOINT event requestID: " + eventRequestID); + debugee.clearEventRequest(JDWP.EventKind.BREAKPOINT, eventRequestID); + log.display(" ... request removed"); + } + + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" no out data"); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no out data + log.display(" no out data"); + + log.display(" ... packet data is parsed"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: EventRequest + * command: ClearAllBreakpoints + * Test checks that debuggee accept tested command and replies + * with correct reply packet, even if all requests for breakpoint + * event had been cleared before. + * Test consists of two compoments: + * debugger: clrallbreakp003 + * debuggee: clrallbreakp003a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded into debuggee, + * makes request for BREAKPOINT at method run() and immediately + * cleares this request. + * Then, debugger creates command packet for tested command + * EventRequest.ClearAllBreakpoints, sends it to debuggee, waits + * for reply packet and checks that reply is correct and has no + * reply data. + * Finally, debugger disconnectes debuggee, waits for it exits + * and exits too with proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp003 + * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp003 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.EventRequest.ClearAllBreakpoints; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class clrallbreakp003a { + + static final int BREAKPOINT_LINE = 80; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + clrallbreakp003a _clrallbreakp003a = new clrallbreakp003a(); + System.exit(clrallbreakp003.JCK_STATUS_BASE + _clrallbreakp003a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass object = new TestedClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + log.display("Invoking method with breakpoint"); + object.run(); + log.display(" ... method invoked"); + + // exit debugee + log.display("Debugee PASSED"); + return clrallbreakp003.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + + public void run() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.Set; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: EventRequest.Set. + * + * See set001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class set001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.EventRequest.Set"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "set001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "EventRequest.Set"; + static final int JDWP_COMMAND_ID = JDWP.Command.EventRequest.Set; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.BREAKPOINT; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + static final byte TESTED_EVENT_MODIFIER = JDWP.EventModifierKind.LOCATION_ONLY; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of field and method of tested class + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = set001a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedMethodID = 0; + int eventRequestID = 0; + JDWP.Location breakpointLocation = null; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new set001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Get debuggee prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + if (success) { + log.display("\n>>> Checking request result \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for BREAKPOINT event + log.display("Waiting for BREAKPOINT event"); + long threadID = debugee.waitForBreakpointEvent(eventRequestID); + log.display(" ... BREAKPOINT event received with threadID: " + threadID); + } + + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debuggee for testing. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for breakpoint method + log.display("Getting breakpoint methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // get codeIndex for breakpoint line + log.display("Getting code index for breakpoint line: " + BREAKPOINT_LINE); + long codeIndex = debugee.getCodeIndex(testedClassID, testedMethodID, BREAKPOINT_LINE); + log.display(" ... got breakpoint codeIndex: " + codeIndex); + + // create breakpoint location + log.display("Creating location for breakpoint at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + breakpointLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, codeIndex); + log.display(" ... got breakpoint location: " + breakpointLocation); + } + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" suspendPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 1); + command.addInt(1); + log.display(" modKind: " + TESTED_EVENT_MODIFIER); + command.addByte(TESTED_EVENT_MODIFIER); + log.display(" location: " + breakpointLocation); + command.addLocation(breakpointLocation); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // extract requestID + int requestID = 0; + try { + requestID = reply.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check requestID + if (requestID == 0) { + log.complain("Unexpected null requestID returned: " + requestID); + success = false; + } + eventRequestID = requestID; + + log.display(" ... packet data is parsed"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Wait for VM_DEATH event. + */ + void waitForVMDeathEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Expected VM_DEATH event received intead of BREAKPOINT event"); + dead = true; + return; + } else if (eventKind == JDWP.EventKind.BREAKPOINT) { + log.complain("Unexpected BREAKPOINT event received in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + } else { + log.complain("Unexpected eventKind of event " + i + " in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in BREAKPOINT event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/EventRequest/Set/set001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: EventRequest + * command: Set + * event kind: BREAKPOINT + * Test checks that debuggee accept tested command and replies + * with correct reply packet. Also test checks that requested + * breakpoint events occurs for created request. + * Test consists of two compoments: + * debugger: set001 + * debuggee: set001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and constructs + * location for breakpoint request. + * Then, debugger creates command packet for command EventRequest.Set + * for this breakpoint location, sends it to debuggee and waits for + * reply packet. When reply packed is received, debugger extracts + * requestID and checks if it is not null. + * Then, debugger resumes debuggee and waits for expected BREAKPOINT + * event. If received event is not BREAKPOINT event, debugger + * complains an error. + * Finally, debugger disconnectes debuggee, waits for it exits + * and exits too with proper exit code. + * COMMENTS + * Test was fixed due to test bug: + * 4797978 TEST_BUG: potential race condition in a number of JDWP tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.EventRequest.Set.set001 + * nsk.jdwp.EventRequest.Set.set001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.EventRequest.Set.set001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.EventRequest.Set; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class set001a { + + static final int BREAKPOINT_LINE = 80; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + set001a _set001a = new set001a(); + System.exit(set001.JCK_STATUS_BASE + _set001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass object = new TestedClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + log.display("Invoking method with breakpoint"); + object.run(); + log.display(" ... method invoked"); + + // exit debugee + log.display("Debugee PASSED"); + return set001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + + public void run() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.Set; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: EventRequest.Set. + * + * See set002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #waitForTestedEvent() + */ +public class set002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.EventRequest.Set"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "set002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "EventRequest.Set"; + static final int JDWP_COMMAND_ID = JDWP.Command.EventRequest.Set; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.VM_START; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new set002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + log.display("Resumindg debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for tested VM_START or VM_DEATH event + log.display("\n>>> Testing JDWP event \n"); + waitForTestedEvent(); + + if (!dead) { + // clear tested request for VM_START event + log.display("\n>>> Clearing request for tested event \n"); + clearTestedRequest(); + + // finish debuggee after testing + log.display("\n>>> Finishing debuggee \n"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for debuggee exited + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + dead = true; + log.display(" ... VM_DEATH event received"); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Test JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" suspendPolicy: " + TESTED_EVENT_SUSPEND_POLICY); + command.addByte(TESTED_EVENT_SUSPEND_POLICY); + log.display(" modifiers: " + 0); + command.addInt(0); + command.setLength(); + log.display(" ... command packet created"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + { + // extract requestID + try { + eventRequestID = reply.getInt(); + log.display(" requestID: " + eventRequestID); + } catch (BoundException e) { + log.complain("Unable to extract requestID from request reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // check requestID + if (eventRequestID == 0) { + log.complain("Unexpected null requestID returned: " + eventRequestID); + success = false; + } + + log.display(" ... packet data is parsed"); + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Clear request for tested VM_START event. + */ + void clearTestedRequest() { + Failure failure = new Failure("Error occured while clearing request for tested event"); + + // create command packet and fill requred out data + log.display("Create command packet: " + "EventRequest.Clear"); + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + log.display(" event: " + TESTED_EVENT_KIND); + command.addByte(TESTED_EVENT_KIND); + log.display(" requestID: " + eventRequestID); + command.addInt(eventRequestID); + log.display(" ... command packet composed"); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + log.display(" ... command packet sent"); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + throw failure; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + throw failure; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" .. packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + throw failure; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + log.display(" no data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... reply packet parsed"); + } + + /** + * Wait for tested CLASS_UNLOAD event. + */ + void waitForTestedEvent() { + + EventPacket eventPacket = null; + + // receive reply packet from debugee + try { + log.display("Waiting for event packet (for " + timeout + "ms timeout)"); + eventPacket = debugee.getEventPacket(timeout); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.complain("Unable to read tested event packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in tested event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check if VM_DEATH event + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Got VM_DEATH event while waiting for tested event"); + dead = true; + log.display("No VM_START event occured so treat test as PASSED"); + return; + } + + // check eventKind + if (eventKind != JDWP.EventKind.VM_START) { + log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + return; + } + + if (eventKind == JDWP.EventKind.VM_START) { + log.complain("Unexpected VM_START event " + i + " in tested event packet: " + + eventKind + " (expected: " + JDWP.EventKind.VM_DEATH + ")"); + success = false; + return; + } + // check suspendPolicy value + if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { + log.complain("Unexpected SuspendPolicy in tested event packet: " + + suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); + success = false; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in tested event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check threadID + if (threadID == 0) { + log.complain("Unexpected threadID of event " + i + " in tested event packet: " + + requestID + " (expected: not 0)"); + success = false; + } + + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/EventRequest/Set/set002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: EventRequest + * command: Set + * event kind: VM_START + * Test checks that debuggee accepts tested command and replies + * with no error code for VM_START event request. The tests also + * checks that requested VM_START event is never received after + * initial automatically generated VM_START event. + * Test consists of two compoments: + * debugger: set002 + * debuggee: set002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Then, debugger creates creates command packet for command + * EventRequest.Set with VM_START event and no event modifiers; + * and sends it to debuggee. After reply packet is received + * debuggeer checks if it has no errors and valid requestID. + * Then, debugger lets debuggee to run and exit and waits for any event + * is received. If VM_START event is received, then debugger complains + * error and removes event request. Otherwise, if event is VM_DEATH + * the test passes. + * Finally, debugger disconnectes debuggee, waits for it exits + * and exits too with proper exit code. + * COMMENTS + * Test fixed due to test bug: + * 4909273 TEST_BUG: Fix nsk/jdwp/EventRequest/Set/set002 + * Test fixed due to test bug: + * 4973741 nsk/jdwp/EventRequest/Set/set002 expects request for VMStart event to fail + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.EventRequest.Set.set002 + * nsk.jdwp.EventRequest.Set.set002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.EventRequest.Set.set002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.EventRequest.Set; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class set002a { + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + set002a _set002a = new set002a(); + System.exit(set002.JCK_STATUS_BASE + _set002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // exit debugee + log.display("Debugee PASSED"); + return set002.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.Bytecodes; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Method.Bytecodes. + * + * See bytecodes001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class bytecodes001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Method.Bytecodes"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "bytecodes001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_GET_BYTECODES; + static final String VM_CAPABILITY_NAME = "canGetBytecodes"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Method.Bytecodes"; + static final int JDWP_COMMAND_ID = JDWP.Command.Method.Bytecodes; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // tested method name constant + static final String TESTED_METHOD_NAME = "testedMethod"; + + // expected values for bound line numbers + static final int FIRST_LINE_NUMBER = bytecodes001a.FIRST_LINE_NUMBER; + static final int LAST_LINE_NUMBER = bytecodes001a.LAST_LINE_NUMBER; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new bytecodes001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Checking VM capability \n"); + + // check for VM capability + log.display("Checking VM capability: " + VM_CAPABILITY_NAME); + if (!debugee.getCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME)) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for methodID of tested method (declared in the class) + log.display("Getting methodID by name: " + TESTED_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classID, methodID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long classID, long methodID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" referenceTypeID: " + classID); + command.addReferenceTypeID(classID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check reply data + + // extract number of lines + int bytes = 0; + try { + bytes = reply.getInt(); + log.display(" bytes: " + bytes); + } catch (BoundException e) { + log.complain("Unable to extract number of bytes from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + if (bytes < 0) { + log.complain("Negative number of bytes in reply packet: " + bytes); + success = false; + return; + } + + if (bytes == 0) { + log.complain("Zero number of bytes in reply packet: " + bytes); + success = false; + return; + } + + // extract all bytes + ByteBuffer bytecode = new ByteBuffer(); + for (int i = 0; i < bytes; i++) { + // extract next byte of bytecode + try { + byte aByte = reply.getByte(); + bytecode.addByte(aByte); + } catch (BoundException e) { + log.complain("Unable to extract byte #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + } + + log.display(" bytecode:\n" + bytecode); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Method/Bytecodes/bytecodes001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Method + * command: Bytecodes + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: bytecodes001 + * debuggee: bytecodes001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID and methodID for the tested class + * and method from debuggee. + * Then, debugger creates command packet for Method.Bytecodes command + * with the found classID and methodID as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts all bytes of bytecode for requested method. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Method.Bytecodes.bytecodes001 + * nsk.jdwp.Method.Bytecodes.bytecodes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Method.Bytecodes.bytecodes001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.Bytecodes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class bytecodes001a { + + public static final int FIRST_LINE_NUMBER = 65; + public static final int LAST_LINE_NUMBER = 76; + + public static void main(String args[]) { + bytecodes001a _bytecodes001a = new bytecodes001a(); + System.exit(bytecodes001.JCK_STATUS_BASE + _bytecodes001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + bytecodes001.READY); + pipe.println(bytecodes001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + bytecodes001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(bytecodes001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + bytecodes001.QUIT + ")"); + log.display("Debugee FAILED"); + return bytecodes001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return bytecodes001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public void testedMethod() { + foo = 1; // foo == 1 + foo++; // foo == 2 + foo++; // foo == 3 + foo++; // foo == 4 + foo++; // foo == 5 + foo++; // foo == 6 + foo++; // foo == 7 + foo++; // foo == 8 + foo++; // foo == 9 + foo++; // foo == 10 + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.IsObsolete; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Method.IsObsolete. + * + * See isobsolete001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class isobsolete001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Method.IsObsolete"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "isobsolete001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_REDEFINE_CLASSES; + static final String VM_CAPABILITY_NAME = "canRedefineClasses"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Method.IsObsolete"; + static final int JDWP_COMMAND_ID = JDWP.Command.Method.IsObsolete; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // tested method name constant + static final String TESTED_METHOD_NAME = "testedMethod"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new isobsolete001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Checking VM capability \n"); + + // check for VM capability + log.display("Checking VM capability: " + VM_CAPABILITY_NAME); + if (!debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME)) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for methodID of tested method (declared in the class) + log.display("Getting methodID by name: " + TESTED_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classID, methodID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long classID, long methodID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" referenceTypeID: " + classID); + command.addReferenceTypeID(classID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract boolean result + byte isObsolete = 0; + try { + isObsolete = reply.getByte(); + log.display(" isObsolete: " + isObsolete); + } catch (BoundException e) { + log.complain("Unable to extract isObsolete value from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that result value is false + if (isObsolete != 0) { + log.complain("Unexpected true isObsolete value received for not obsolete method: " + + isObsolete); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Method/IsObsolete/isobsolete001. + * VM Testbase keywords: [quick, jpda, jdwp, redefine] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Method + * command: IsObsolete + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * return value is false, because method of not redefined class + * is not obsolete. + * Test consists of two compoments: + * debugger: isobsolete001 + * debuggee: isobsolete001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID and methodID for the tested class + * and method from debuggee. + * Then, debugger creates command packet for Method.IsObsolete command + * with the found classID and methodID as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts boolean isObsolete value. Also test checks that extracted + * value is false. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Method.IsObsolete.isobsolete001 + * nsk.jdwp.Method.IsObsolete.isobsolete001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Method.IsObsolete.isobsolete001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.IsObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class isobsolete001a { + + public static void main(String args[]) { + isobsolete001a _isobsolete001a = new isobsolete001a(); + System.exit(isobsolete001.JCK_STATUS_BASE + _isobsolete001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + isobsolete001.READY); + pipe.println(isobsolete001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + isobsolete001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(isobsolete001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + isobsolete001.QUIT + ")"); + log.display("Debugee FAILED"); + return isobsolete001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return isobsolete001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public void testedMethod() { + foo = 1; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.IsObsolete; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Method.IsObsolete. + * + * See isobsolete002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class isobsolete002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_REDEFINE_CLASSES; + static final String VM_CAPABILITY_NAME = "canRedefineClasses"; + + // package and classes names + static final String PACKAGE_NAME = "nsk.jdwp.Method.IsObsolete"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "isobsolete002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command + static final String JDWP_COMMAND_NAME = "Method.IsObsolete"; + static final int JDWP_COMMAND_ID = JDWP.Command.Method.IsObsolete; + + // tested class name and signature + static final String TESTED_CLASS_NAME = TEST_CLASS_NAME + "b"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // tested method name + static final String TESTED_METHOD_NAME = "testedMethod"; + static final int BREAKPOINT_LINE = isobsolete002a.BREAKPOINT_LINE; + + // filename for redefined class +// 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS +// precomiled class was removed +// static final String REDEFINED_CLASS_FILE_NAME = "isobsolete002b.klass"; + static final String REDEFINED_CLASS_FILE_NAME = "newclass" + + File.separator + PACKAGE_NAME.replace('.',File.separatorChar) + + File.separator + "isobsolete002b.class"; +// + File.separator + "isobsolete002b.klass"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + String testDir = null; + boolean dead = false; + boolean success = true; + + // data obtained from debuggee + long testedClassID = 0; + long testedMethodID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new isobsolete002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); // minutes + timeout = waitTime * 60 * 1000; // milliseconds + + // get testDir as first positional parameter + String args[] = argumentHandler.getArguments(); + if (args.length < 1) { + log.complain("Test dir required as the first positional argument"); + return FAILED; + } + testDir = args[0]; + + // execute test and display results + try { + log.display("\n>>> Loading redefined class \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee VM"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debuggee launched"); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for VM_INIT event + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // check for VM capability + log.display("\n>>> Checking VM capability \n"); + log.display("Getting new VM capability: " + VM_CAPABILITY_NAME); + boolean capable = debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME); + log.display(" ... got VM capability: " + capable); + + // exit as PASSED if this capability is not supported + if (!capable) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // prepare debuggee for testing and obtain required data + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(testedMethodID, TESTED_METHOD_NAME); + + // finish debuggee + log.display("\n>> Finishing debuggee \n"); + + // resume debuggee after testing command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for VM_DEATH event + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + log.display(" ... VM_DEATH event received"); + dead = true; + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + log.display("\n>>> Finishing test \n"); + + // disconnect debugee and wait for its exit + if (debugee != null) { + quitDebugee(); + } + } + + // check result + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + out.println("TEST PASSED"); + return PASSED; + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for debuggee and tested classes loaded on debuggee startup + log.display("Waiting for classes loaded:" + + "\n\t" + TESTED_CLASS_NAME); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, + JDWP.SuspendPolicy.ALL); + log.display(" ... class loaded with classID: " + testedClassID); + log.display(""); + +/* + // get tested methodID by names + log.display("Getting methodID for method name :" + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + log.display(""); +*/ + + // wait for breakpoint reached + log.display("Waiting for breakpoint reached at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + long threadID = debugee.waitForBreakpointReached(testedClassID, + TESTED_METHOD_NAME, + BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint reached with threadID: " + threadID); + log.display(""); + + // load class file for redefined class + log.display("Loading bytecode of redefined class from file: " + + REDEFINED_CLASS_FILE_NAME); + byte[] classBytes = loadClassBytes(REDEFINED_CLASS_FILE_NAME, testDir); + log.display(" ... loaded bytes: " + classBytes.length); + + // redefine class + log.display("Redefine class by classID: " + testedClassID); + redefineClass(testedClassID, classBytes); + log.display(" ... class redefined"); + log.display(""); + + // get top frameID of the thread + log.display("Getting top frameID of the threadID: " + threadID); + JDWP.Location location = queryTopFrameLocation(threadID); + log.display(" ... got location: " + location); + + // get methodID of the top frameID + log.display("Getting methodID for the location :" + location); + testedMethodID = location.getMethodID(); + log.display(" ... got methodID: " + testedMethodID); + log.display(""); + + } + + /** + * Perform testing JDWP command for given methodID. + */ + void testCommand(long testedMethodID, String methodName) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" refTypeID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + log.display(" methodID: " + testedMethodID); + command.addMethodID(testedMethodID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet for method " + methodName + ":\n\t" + e); + success = false; + return; + } + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet for method " + methodName + ":\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for method " + methodName + ":\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // extract boolean isObsolete + byte isObsolete = 0; + try { + isObsolete = reply.getByte(); + log.display(" isObsolete: " + isObsolete); + } catch (BoundException e) { + log.complain("Unable to extract isObsolete value from reply packet for method " + + methodName + ":\n\t" + e.getMessage()); + success = false; + } + + // check isObsolete + if (isObsolete == 0) { + log.complain("Unexpected isObsolete value for method " + + methodName + ": " + isObsolete + " (expected: not " + 0 + ")"); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes in reply packet for " + + methodName + " method at: " + reply.offsetString()); + success = false; + } + + log.display(" ... packed data parsed"); + } + + /** + * Redefine class bytes for given classID. + */ + void redefineClass(long classID, byte[] classBytes) { + int length = classBytes.length; + + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.RedefineClasses); + command.addInt(1); + command.addReferenceTypeID(classID); + command.addInt(length); + command.addBytes(classBytes, 0, length); + + // receive reply packet from debugee + ReplyPacket reply = debugee.receiveReplyFor(command, "VirtualMachine.RedefineClasses"); + } + + /** + * Query debuggee VM for top frameID of the thread. + */ + JDWP.Location queryTopFrameLocation(long threadID) { + String error = "Error occured while getting top frameID for threadID: " + threadID; + + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Frames); + command.addObjectID(threadID); + command.addInt(0); + command.addInt(1); + command.setLength(); + + ReplyPacket reply = debugee.receiveReplyFor(command, "ThreadReference.Frames"); + reply.resetPosition(); + + // extract number of frames + int frames = 0; + try { + frames = reply.getInt(); + } catch (BoundException e) { + log.complain("Unable to extract number of frames from reply packet:\n\t" + + e.getMessage()); + throw new Failure(error); + } + + // check frames count + if (frames != 1) { + log.complain("Unexpected number of frames returned: " + + frames + " (expected: " + 1 + ")"); + throw new Failure(error); + } + + // extract frame ID + long frameID = 0; + try { + frameID = reply.getFrameID(); + } catch (BoundException e) { + log.complain("Unable to extract top frameID from reply packet:\n\t" + + e.getMessage()); + throw new Failure(error); + } + + // extract frame location + JDWP.Location location = null; + try { + location = reply.getLocation(); + } catch (BoundException e) { + log.complain("Unable to extract location for top frame from reply packet:\n\t" + + e.getMessage()); + throw new Failure(error); + } + + return location; + } + + + /** + * Load class bytes form the given file. + */ + byte[] loadClassBytes(String fileName, String dirName) { + String fileSep = System.getProperty("file.separator"); + String filePath = dirName + fileSep + fileName; + + String error = "Unable to read bytes from class file:\n\t" + filePath; + + int length = 0; + byte bytes[] = null; + try { + File file = new File(filePath); + length = (int)file.length(); + FileInputStream is = new FileInputStream(file); + bytes = new byte[length]; + int number = is.read(bytes); + if (number < 0) { + log.complain("EOF reached while reading bytes from file"); + throw new Failure(error); + } else if (number != length) { + log.complain("Unexpected number of bytes red from file: " + number + + " (expected: " + length + ")"); + throw new Failure(error); + } + is.close(); + } catch ( IOException e ) { + log.complain("Caught IOException while reading bytes from file:\n\t" + e); + throw new Failure(error); + } + return bytes; + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Method/IsObsolete/isobsolete002. + * VM Testbase keywords: [quick, jpda, jdwp, redefine] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Method + * command: IsObsolete + * Test checks that debugee accept the command packet and + * replies with correct reply packet after class redefinition + * for redefined method being at that time with active stack + * frame. + * Test consists of two compoments: + * debugger: isobsolete002 + * debuggee: isobsolete002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * It waits for tested class is loaded, sets breakpoint on the tested + * method, and waits for breakpoint is reached. + * Then, it loads bytecode of redefined class from *.klass file and + * redefines the class. After class redefinition, debugger queries + * debiggi for the methodID of to level stack frame and checks this + * method. + * Debugger creates command packet with Method.IsObsolete command for + * the tested method, writes this packet to the transport channel, + * and waits for a reply packet. When reply packet is received, + * debugger parses the packet structure and checks if expected + * isObsolete value returned in the packet. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * First positional argument for the test should be path to the test + * work directory where loaded *.klass file should be located. + * Test was fixed due to test bug: + * 4514956 Method.isObsolete() returns false for redefined method + * Test was updated according to rfe: + * 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS. + * isobsolete002b.ja was moved into newclass directory and renamed + * to isobsolete002b.java. + * The precompiled class file is created during test base build process. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build ExecDriver + * @build nsk.jdwp.Method.IsObsolete.isobsolete002 + * nsk.jdwp.Method.IsObsolete.isobsolete002a + * nsk.jdwp.Method.IsObsolete.isobsolete002b + * @run driver PropertyResolvingWrapper ExecDriver --cmd + * ${compile.jdk}/bin/javac + * -cp ${test.class.path} + * -d newclass + * newclass/isobsolete002b.java + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Method.IsObsolete.isobsolete002 + * . + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/newclass/isobsolete002b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/newclass/isobsolete002b.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Method.IsObsolete; + +import nsk.share.*; + +/** + * This class is for redefinition. + */ +public class isobsolete002b { + + // static field + public static int staticField = 0; + // object field + public int objectField = 0; + + public static Log log; + + // method to be redefined + public void testedMethod(int arg) { + log.display("Object method invoked: REDEFINED and MODIFIED"); // isobsolete002a.BREAKPOINT_LINE + objectField = arg; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.IsObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class isobsolete002a { + + // scaffold objects + static volatile ArgumentHandler argumentHandler = null; + static volatile Log log = null; + + // breakpoint line in isobsolete002b + static final int BREAKPOINT_LINE = 44; + + public static void main(String args[]) { + System.exit(isobsolete002.JCK_STATUS_BASE + isobsolete002a.runIt(args, System.err)); + } + + public static int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating object of tested class"); + isobsolete002b.log = log; + isobsolete002b object = new isobsolete002b(); + log.display(" ... object created"); + + log.display("Invoking tested method before class redefinition"); + object.testedMethod(100); + log.display(" ... tested method invoked"); + + log.display("Invoking tested method after class redefinition"); + object.testedMethod(100); + log.display(" ... tested method invoked"); + + // exit + log.display("Debugee PASSED"); + return isobsolete002.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002b.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Method.IsObsolete; + +import nsk.share.*; + +/** + * This class is to be redefined. + */ +public class isobsolete002b { + + // static field + public static int staticField = 0; + // object field + public int objectField = 0; + + public static Log log; + + // tested method to be redefined + public void testedMethod(int arg) { + int value = arg; // isobsolete002a.BREAKPOINT_LINE + log.display("Object method invoked: NOT_REDEFINED"); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.LineTable; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Method.LineTable. + * + * See linetable001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class linetable001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Method.LineTable"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "linetable001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Method.LineTable"; + static final int JDWP_COMMAND_ID = JDWP.Command.Method.LineTable; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // tested method name constant + static final String TESTED_METHOD_NAME = "testedMethod"; + + // expected values for bound line numbers + static final int FIRST_LINE_NUMBER = linetable001a.FIRST_LINE_NUMBER; + static final int LAST_LINE_NUMBER = linetable001a.LAST_LINE_NUMBER; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new linetable001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for methodID of tested method (declared in the class) + log.display("Getting methodID by name: " + TESTED_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classID, methodID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long classID, long methodID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" referenceTypeID: " + classID); + command.addReferenceTypeID(classID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check reply data + + // extract start code index + long start = 0; + try { + start = reply.getLong(); + log.display(" start: " + start); + } catch (BoundException e) { + log.complain("Unable to extract start line index from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that start code index is not negative + if (start < 0) { + log.complain("Negative value of start code index in reply packet: " + start); + success = false; + } + + // extract end code index + long end = 0; + try { + end = reply.getLong(); + log.display(" end: " + end); + } catch (BoundException e) { + log.complain("Unable to extract end line index from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that end code index is not negative + if (start < 0) { + log.complain("Negative value of end code index in reply packet: " + end); + success = false; + } + + // check that start code is strongly less than end code index + if (start > end) { + log.complain("Start code index (" + start + + ") is greater than end code index (" + end + ")"); + success = false; + } else if (start == end) { + log.complain("Start code index (" + start + + ") is equal to end code index (" + end + ")"); + success = false; + } + + // extract number of lines + int lines = 0; + try { + lines = reply.getInt(); + log.display(" lines: " + lines); + } catch (BoundException e) { + log.complain("Unable to extract number of lines from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + if (lines < 0) { + log.complain("Negative number of lines in reply packet: " + lines); + success = false; + return; + } + + if (lines == 0) { + log.complain("Zero number of lines in reply packet: " + lines); + success = false; + return; + } + + // extract and check each line attributes + long lineCodeIndex = 0, prevLineCodeIndex = 0; + int lineNumber = 0, prevLineNumber = 0; + + for (int i = 0; i < lines; i++) { + log.display(" line #" + i + ":"); + + // extract code index of a line + try { + lineCodeIndex = reply.getLong(); + log.display(" lineCodeIndex: " + lineCodeIndex); + } catch (BoundException e) { + log.complain("Unable to extract code index of line #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that code index is between start and end values + if (lineCodeIndex < start) { + log.complain("Code index of line #" + i + " (" + lineCodeIndex + + ") is less than start code index (" + start + ")"); + success = false; + } + + if (lineCodeIndex > end) { + log.complain("Code index of line #" + i + " (" + lineCodeIndex + + ") is greater than end code index (" + end + ")"); + success = false; + } + + // check that code index ot the first line is equal to start value + if (i == 0) { + if (lineCodeIndex != start) { + log.complain("Code index of first line (" + lineCodeIndex + + ") is not equal to start code index (" + start + ")"); + success = false; + } + } + + // check that code index of a line is strongly greater than for previous line + if (i > 0) { + if (lineCodeIndex < prevLineCodeIndex) { + log.complain("Code index of line #" + i + " (" + lineCodeIndex + + ") is less than code index of previous line (" + + prevLineCodeIndex + ")"); + success = false; + } else if (lineCodeIndex == prevLineCodeIndex) { + log.complain("Code index of line #" + i + " (" + lineCodeIndex + + ") is equal to code index of previous line (" + + prevLineCodeIndex + ")"); + success = false; + } + } + + // extract number of a line + try { + lineNumber = reply.getInt(); + log.display(" lineNumber: " + lineNumber); + } catch (BoundException e) { + log.complain("Unable to extract number of line #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that code index ot the line is not negative + if (lineNumber < 0) { + log.complain("Number of line #" + i + " (" + lineNumber + + ") is negative"); + success = false; + } + + // check that code index ot the line is not less than expected + if (lineNumber < FIRST_LINE_NUMBER) { + log.complain("Number of line #" + i + " (" + lineNumber + + ") is less than expected (" + FIRST_LINE_NUMBER + ")"); + success = false; + } + + // check that code index ot the line is not greater than expected + if (lineNumber > LAST_LINE_NUMBER) { + log.complain("Number of line #" + i + " (" + lineNumber + + ") is greater than expected (" + LAST_LINE_NUMBER + ")"); + success = false; + } + + // check that line number follows directly to the number of previous line + if (i > 0) { + if (lineNumber < prevLineNumber) { + log.complain("Number of line #" + i + " (" + lineCodeIndex + + ") is less than number of previous line (" + + prevLineNumber + ")"); + success = false; + } else if (lineNumber == prevLineNumber) { + log.complain("Number of line #" + i + " (" + lineCodeIndex + + ") is equal to number of previous line (" + + prevLineNumber + ")"); + success = false; + } else if (lineNumber != prevLineNumber + 1) { + log.complain("Number of line #" + i + " (" + lineCodeIndex + + ") does not follows to number of previous line (" + + prevLineNumber + ")"); + success = false; + } + } + + // save values to use them as previous line attributes + prevLineCodeIndex = lineCodeIndex; + prevLineNumber = lineNumber; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Method/LineTable/linetable001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Method + * command: LineTable + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that code index and number for returned lines + * have expected values, namely: + * 1) start code index is strongly less than + * end code index + * and for each line: + * 2) line code index is between start and end code index + * 3) line code index for previous line is strongly less + * then for next line + * 4) line number is between start and end line number + * 5) line number for previous line is no greater + * then for next line + * 6) number of next line follows directly to the number + * of previous line + * Test consists of two compoments: + * debugger: linetable001 + * debuggee: linetable001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID and methodID for the tested class + * and method from debuggee. + * Then, debugger creates command packet for Method.LineTable command + * with the found classID and methodID as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts code index and number for each lines. Also test + * checks above mentioned assertions. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Method.LineTable.linetable001 + * nsk.jdwp.Method.LineTable.linetable001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Method.LineTable.linetable001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.Method.LineTable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class linetable001a { + + public static final int FIRST_LINE_NUMBER = 86; + public static final int LAST_LINE_NUMBER = 97; + + public static void main(String args[]) { + linetable001a _linetable001a = new linetable001a(); + System.exit(linetable001.JCK_STATUS_BASE + _linetable001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + linetable001.READY); + pipe.println(linetable001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + linetable001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(linetable001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + linetable001.QUIT + ")"); + log.display("Debugee FAILED"); + return linetable001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return linetable001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public void testedMethod() { // FIRST_LINE_NUMBER + foo = 1; // foo == 1 + foo++; // foo == 2 + foo++; // foo == 3 + foo++; // foo == 4 + foo++; // foo == 5 + foo++; // foo == 6 + foo++; // foo == 7 + foo++; // foo == 8 + foo++; // foo == 9 + foo++; // foo == 10 + } // LAST_LINE_NUMBER + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.VariableTable; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Method.VariableTable. + * + * See vartable001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class vartable001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Method.VariableTable"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "vartable001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Method.VariableTable"; + static final int JDWP_COMMAND_ID = JDWP.Command.Method.VariableTable; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // tested types signature conatants + static final String OBJECT_CLASS_SIGNATURE = "Ljava/lang/Object;"; + static final String STRING_CLASS_SIGNATURE = "Ljava/lang/String;"; + + + // tested method name constant + static final String TESTED_METHOD_NAME = "testedMethod"; + + // list of tested variables names and signatures + static final String variablesList[][] = { + // synthetic method arguments + {"this", TESTED_CLASS_SIGNATURE}, + // method arguments + {"booleanArgument", "Z"}, + {"byteArgument", "B"}, + {"charArgument", "C"}, + {"shortArgument", "S"}, + {"intArgument", "I"}, + {"longArgument", "J"}, + {"floatArgument", "F"}, + {"doubleArgument", "D"}, + {"objectArgument", OBJECT_CLASS_SIGNATURE}, + {"stringArgument", STRING_CLASS_SIGNATURE}, + // local variables + {"booleanLocal", "Z"}, + {"byteLocal", "B"}, + {"charLocal", "C"}, + {"shortLocal", "S"}, + {"intLocal", "I"}, + {"longLocal", "J"}, + {"floatLocal", "F"}, + {"doubleLocal", "D"}, + {"objectLocal", OBJECT_CLASS_SIGNATURE}, + {"stringLocal", STRING_CLASS_SIGNATURE} + }; + static final int variablesCount = variablesList.length; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new vartable001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for methodID of tested method (declared in the class) + log.display("Getting methodID by name: " + TESTED_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classID, methodID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long classID, long methodID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" referenceTypeID: " + classID); + command.addReferenceTypeID(classID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // clear list of found variables + int[] foundVariablesList = new int[variablesCount]; + for (int i = 0; i < variablesCount; i++) { + foundVariablesList[i] = 0; + } + + // extract and check reply data + + // extract number of argumnets + int argCount = 0; + try { + argCount = reply.getInt(); + log.display(" argCount: " + argCount); + } catch (BoundException e) { + log.complain("Unable to extract number of arguments from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that number of arguments is not negative + if (argCount < 0) { + log.complain("Negative of arguments in reply packet: " + argCount); + success = false; + } + + // extract number of slots + int slots = 0; + try { + slots = reply.getInt(); + log.display(" slots: " + slots); + } catch (BoundException e) { + log.complain("Unable to extract number of slots from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that number of slots is not negative + if (slots < 0) { + log.complain("Negative value of end code index in reply packet: " + slots); + success = false; + } + + // check that start code is not less than expected + if (slots < variablesCount) { + log.complain("Number of slots (" + slots + + ") is less than expected (" + variablesCount + ")"); + success = false; + } + + // extract and check each slot attributes + for (int i = 0; i < slots; i++) { + log.display(" slot #" + i + ":"); + + // extract code index of a slot + long codeIndex = 0; + try { + codeIndex = reply.getLong(); + log.display(" codeIndex: " + codeIndex); + } catch (BoundException e) { + log.complain("Unable to extract code index of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that code index is not negative + if (codeIndex < 0) { + log.complain("Negative code index of slot #" + i + ":" + codeIndex); + success = false; + } + + // extract name of a slot + String name = null; + try { + name = reply.getString(); + log.display(" name: " + name); + } catch (BoundException e) { + log.complain("Unable to extract name of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract signature of a slot + String signature = null; + try { + signature = reply.getString(); + log.display(" signature: " + signature); + } catch (BoundException e) { + log.complain("Unable to extract signature of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract code length + int length = 0; + try { + length = reply.getInt(); + log.display(" length: " + length); + } catch (BoundException e) { + log.complain("Unable to extract code length for slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract code length + int slot = 0; + try { + slot = reply.getInt(); + log.display(" slot: " + length); + } catch (BoundException e) { + log.complain("Unable to extract slot index of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // find slot name into list of expected variables + int found = -1; + for (int j = 0; j < variablesCount; j++) { + if (variablesList[j][0].equals(name)) { + found = j; + break; + } + } + + // check if slot is found and not duplicated + if (found >= 0) { + if (foundVariablesList[found] > 0) { + log.complain("Slot #" + i + " is duplicated " + + foundVariablesList[found] + " times: " + + name); + success = false; +/* + } else { + log.display("Found expected variable #" + found + ": " + + variablesList[found][0]); +*/ + } + foundVariablesList[found]++; + + // check slot signature + if (!variablesList[found][1].equals(signature)) { + log.complain("Unexpected signature for slot #" + i + ": " + signature + + " (expected: " + variablesList[found][1] + ")"); + success = false; + } + } else { + log.display("Unexpected slot #" + i + " (may be synthetic): " + name); + } + + // check that code length is not negative + if (length < 0) { + log.complain("Code length for slot #" + i + " is negative: " + length); + success = false; + } + + // check that slot index is not negative + if (slot < 0) { + log.complain("Index of slot #" + i + " is negative: " + slot); + success = false; + } + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that all expected variables found + for (int i = 0; i < variablesCount; i++) { + if (foundVariablesList[i] <= 0) { + log.complain("No slot found in reply packet for variable: " + + variablesList[i][0]); + success = false; + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Method/VariableTable/vartable001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Method + * command: VariableTable + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that names and signatures of returned + * arguments and local variables are equal to expected ones. + * Test consists of two compoments: + * debugger: vartable001 + * debuggee: vartable001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID and methodID for the tested class + * and method from debuggee. + * Then, debugger creates command packet for Method.VariableTable command + * with the found classID and methodID as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts attributes of all arguments and variables. Also test + * checks that extracted attributes have expected values. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Method.VariableTable.vartable001 + * nsk.jdwp.Method.VariableTable.vartable001a + * @comment debuggee should be compiled w/ debug info + * @clean nsk.jdwp.Method.VariableTable.vartable001a + * @compile -g:lines,source,vars ../vartable001a.java + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Method.VariableTable.vartable001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.VariableTable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class vartable001a { + + public static void main(String args[]) { + vartable001a _vartable001a = new vartable001a(); + System.exit(vartable001.JCK_STATUS_BASE + _vartable001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + vartable001.READY); + pipe.println(vartable001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + vartable001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(vartable001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + vartable001.QUIT + ")"); + log.display("Debugee FAILED"); + return vartable001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return vartable001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + // tested method + public void testedMethod( + boolean booleanArgument, + byte byteArgument, + char charArgument, + short shortArgument, + int intArgument, + long longArgument, + float floatArgument, + double doubleArgument, + Object objectArgument, + String stringArgument + ) { + + boolean booleanLocal = booleanArgument; + byte byteLocal = byteArgument; + char charLocal = charArgument; + short shortLocal = shortArgument; + int intLocal = intArgument; + long longLocal = longArgument; + float floatLocal = floatArgument; + double doubleLocal = doubleArgument; + Object objectLocal = objectArgument; + String stringLocal = stringArgument; + + System.out.println( + "booleanLocal = " + booleanLocal + "\n" + + "byteLocal = " + byteLocal + "\n" + + "charLocal = " + charLocal + "\n" + + "shortLocal = " + shortLocal + "\n" + + "intLocal = " + intLocal + "\n" + + "longLocal = " + longLocal + "\n" + + "floatLocal = " + floatLocal + "\n" + + "doubleLocal = " + doubleLocal + "\n" + + "objectLocal = " + objectLocal + "\n" + + "stringLocal = " + stringLocal + "\n" + ); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.VariableTableWithGeneric; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: Method.VariableTableWithGeneric. + * + * See vartblwithgen001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class vartblwithgen001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.Method.VariableTableWithGeneric"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "vartblwithgen001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "Method.VariableTableWithGeneric"; + static final int JDWP_COMMAND_ID = JDWP.Command.Method.VariableTableWithGeneric; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String THIS_GENERIC_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + "" + ";"; + + // tested types signature conatants + static final String OBJECT_CLASS_SIGNATURE = "Ljava/lang/Object;"; + static final String STRING_CLASS_SIGNATURE = "Ljava/lang/String;"; + + + // tested method name constant + static final String TESTED_METHOD_NAME = "testedMethod"; + + // list of tested variables names and signatures + static final String variablesList[][] = { + + // synthetic arguments + {"this", TESTED_CLASS_SIGNATURE, THIS_GENERIC_SIGNATURE}, + + // not generic arguments + {"arg11PrimBoolean", "Z", ""}, + {"arg12PrimInt", "I", ""}, + {"arg13Object", "Ljava/lang/Object;", ""}, + {"arg14String", "Ljava/lang/String;", ""}, + {"arg15PrimArrShort", "[S", ""}, + {"arg16ObjArrObject", "[Ljava/lang/Object;", ""}, + + // generic arguments + {"arg21GenObject", "Ljava/lang/Object;", "TT;"}, + {"arg22GenNumber", "Ljava/lang/Number;", "TN;"}, + {"arg23GenObjectArr", "[Ljava/lang/Object;", "[TT;"}, + {"arg24GenNumberArr", "[Ljava/lang/Number;", "[TN;"}, + {"arg25GenObjectList", "Ljava/util/List;", "Ljava/util/List;"}, + {"arg26GenNumberList", "Ljava/util/List;", "Ljava/util/List;"}, + {"arg27GenObjectDerivedList", "Ljava/util/List;", "Ljava/util/List<+TT;>;"}, + {"arg28GenNumberDerivedList", "Ljava/util/List;", "Ljava/util/List<+TN;>;"}, + + // not generic variables + {"var11PrimBoolean", "Z", ""}, + {"var12PrimInt", "I", ""}, + {"var13Object", "Ljava/lang/Object;", ""}, + {"var14String", "Ljava/lang/String;", ""}, + {"var15PrimArrShort", "[S", ""}, + {"var16ObjArrObject", "[Ljava/lang/Object;", ""}, + + // generic variables + {"var21GenObject", "Ljava/lang/Object;", "TT;"}, + {"var22GenNumber", "Ljava/lang/Number;", "TN;"}, + {"var23GenObjectArr", "[Ljava/lang/Object;", "[TT;"}, + {"var24GenNumberArr", "[Ljava/lang/Number;", "[TN;"}, + {"var25GenObjectList", "Ljava/util/List;", "Ljava/util/List;"}, + {"var26GenNumberList", "Ljava/util/List;", "Ljava/util/List;"}, + {"var27GenObjectDerivedList", "Ljava/util/List;", "Ljava/util/List<+TT;>;"}, + {"var28GenNumberDerivedList", "Ljava/util/List;", "Ljava/util/List<+TN;>;"}, + + }; + static final int variablesCount = variablesList.length; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new vartblwithgen001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for methodID of tested method (declared in the class) + log.display("Getting methodID by name: " + TESTED_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(classID, methodID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long classID, long methodID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" referenceTypeID: " + classID); + command.addReferenceTypeID(classID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // clear list of found variables + int[] foundVariablesList = new int[variablesCount]; + for (int i = 0; i < variablesCount; i++) { + foundVariablesList[i] = 0; + } + + // extract and check reply data + + // extract number of argumnets + int argCount = 0; + try { + argCount = reply.getInt(); + log.display(" argCount: " + argCount); + } catch (BoundException e) { + log.complain("Unable to extract number of arguments from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that number of arguments is not negative + if (argCount < 0) { + log.complain("Negative of arguments in reply packet: " + argCount); + success = false; + } + + // extract number of slots + int slots = 0; + try { + slots = reply.getInt(); + log.display(" slots: " + slots); + } catch (BoundException e) { + log.complain("Unable to extract number of slots from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that number of slots is not negative + if (slots < 0) { + log.complain("Negative value of end code index in reply packet: " + slots); + success = false; + } + + // check that start code is not less than expected + if (slots < variablesCount) { + log.complain("Number of slots (" + slots + + ") is less than expected (" + variablesCount + ")"); + success = false; + } + + // extract and check each slot attributes + for (int i = 0; i < slots; i++) { + log.display(" slot #" + i + ":"); + + // extract code index of a slot + long codeIndex = 0; + try { + codeIndex = reply.getLong(); + log.display(" codeIndex: " + codeIndex); + } catch (BoundException e) { + log.complain("Unable to extract code index of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that code index is not negative + if (codeIndex < 0) { + log.complain("Negative code index of slot #" + i + ":" + codeIndex); + success = false; + } + + // extract name of a slot + String name = null; + try { + name = reply.getString(); + log.display(" name: " + name); + } catch (BoundException e) { + log.complain("Unable to extract name of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract signature of a slot + String signature = null; + try { + signature = reply.getString(); + log.display(" signature: " + signature); + } catch (BoundException e) { + log.complain("Unable to extract signature of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract generic signature of a slot + String genericSignature = null; + try { + genericSignature = reply.getString(); + log.display(" generic: " + genericSignature); + } catch (BoundException e) { + log.complain("Unable to extract generic signature of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract code length + int length = 0; + try { + length = reply.getInt(); + log.display(" length: " + length); + } catch (BoundException e) { + log.complain("Unable to extract code length for slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract code length + int slot = 0; + try { + slot = reply.getInt(); + log.display(" slot: " + length); + } catch (BoundException e) { + log.complain("Unable to extract slot index of slot #" + i + + " from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // find slot name into list of expected variables + int found = -1; + for (int j = 0; j < variablesCount; j++) { + if (variablesList[j][0].equals(name)) { + found = j; + break; + } + } + + // check if slot is found and not duplicated + if (found >= 0) { + if (foundVariablesList[found] > 0) { + log.complain("Slot #" + i + " is duplicated " + + foundVariablesList[found] + " times: " + + name); + success = false; +/* + } else { + log.display("Found expected variable #" + found + ": " + + variablesList[found][0]); +*/ + } + foundVariablesList[found]++; + + // check slot signature + if (!variablesList[found][1].equals(signature)) { + log.complain("Unexpected signature for slot #" + i + ": " + signature + + " (expected: " + variablesList[found][1] + ")"); + success = false; + } + + // check slot generic signature + if (variablesList[found][2] == null && genericSignature != null) { + log.complain("Unexpected generic signature for slot #" + i + ": " + genericSignature + + " (expected: " + variablesList[found][2] + ")"); + success = false; + } else if (!variablesList[found][2].equals(genericSignature)) { + log.complain("Unexpected generic signature for slot #" + i + ": " + genericSignature + + " (expected: " + variablesList[found][2] + ")"); + success = false; + } + + } else { + log.display("Unexpected slot #" + i + " (may be synthetic): " + name); + } + + // check that code length is not negative + if (length < 0) { + log.complain("Code length for slot #" + i + " is negative: " + length); + success = false; + } + + // check that slot index is not negative + if (slot < 0) { + log.complain("Index of slot #" + i + " is negative: " + slot); + success = false; + } + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that all expected variables found + for (int i = 0; i < variablesCount; i++) { + if (foundVariablesList[i] <= 0) { + log.complain("No slot found in reply packet for variable: " + + variablesList[i][0]); + success = false; + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: Method + * command: VariableTableWithGeneric + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that names and generic signatures of returned + * arguments and local variables are equal to expected ones. + * Test consists of two compoments: + * debugger: vartblwithgen001 + * debuggee: vartblwithgen001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID and methodID for the tested class + * and method from debuggee. + * Then, debugger creates command packet for Method.VariableTableWithGeneric + * command with the found classID and methodID as arguments, writes packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts attributes of all arguments and variables. Also test + * checks that extracted attributes have expected values. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.Method.VariableTableWithGeneric.vartblwithgen001 + * nsk.jdwp.Method.VariableTableWithGeneric.vartblwithgen001a + * @comment debuggee should be compiled w/ debug info + * @clean nsk.jdwp.Method.VariableTableWithGeneric.vartblwithgen001a + * @compile -g:lines,source,vars ../vartblwithgen001a.java + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.Method.VariableTableWithGeneric.vartblwithgen001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.Method.VariableTableWithGeneric; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; +import java.util.*; + +/** + * This class represents debuggee part in the test. + */ +public class vartblwithgen001a { + + public static void main(String args[]) { + vartblwithgen001a _vartblwithgen001a = new vartblwithgen001a(); + System.exit(vartblwithgen001.JCK_STATUS_BASE + _vartblwithgen001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + vartblwithgen001.READY); + pipe.println(vartblwithgen001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + vartblwithgen001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(vartblwithgen001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + vartblwithgen001.QUIT + ")"); + log.display("Debugee FAILED"); + return vartblwithgen001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return vartblwithgen001.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + // tested method + public void testedMethod( + // not generic argumments + boolean arg11PrimBoolean, + int arg12PrimInt, + Object arg13Object, + String arg14String, + short[] arg15PrimArrShort, + Object[] arg16ObjArrObject, + + // generic arguments + T arg21GenObject, + N arg22GenNumber, + T[] arg23GenObjectArr, + N[] arg24GenNumberArr, + List arg25GenObjectList, + List arg26GenNumberList, + List arg27GenObjectDerivedList, + List arg28GenNumberDerivedList + ) { + + // not generic variables + boolean var11PrimBoolean = arg11PrimBoolean; + int var12PrimInt = arg12PrimInt; + Object var13Object = arg13Object; + String var14String = arg14String; + short[] var15PrimArrShort = arg15PrimArrShort; + Object[] var16ObjArrObject = arg16ObjArrObject; + + // generic variables + T var21GenObject = arg21GenObject; + N var22GenNumber = arg22GenNumber; + T[] var23GenObjectArr = arg23GenObjectArr; + N[] var24GenNumberArr = arg24GenNumberArr; + List var25GenObjectList = arg25GenObjectList; + List var26GenNumberList = arg26GenNumberList; + List var27GenObjectDerivedList = arg27GenObjectDerivedList; + List var28GenNumberDerivedList = arg28GenNumberDerivedList; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.DisableCollection; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.DisableCollection. + * + * See disablecol001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class disablecol001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.DisableCollection"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "disablecol001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.DisableCollection"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.DisableCollection; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String OBJECT_FIELD_NAME = disablecol001a.OBJECT_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new disablecol001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debuggee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long objectID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/DisableCollection/disablecol001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: DisableCollection + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: disablecol001 + * debuggee: disablecol001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for the tested class + * and objectID as the value of the class static field. + * Then, debugger creates command packet for ObjectReference.DisableCollection + * command with the found objectID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks that there is no reply data in the package. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.DisableCollection.disablecol001 + * nsk.jdwp.ObjectReference.DisableCollection.disablecol001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.DisableCollection.disablecol001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.DisableCollection; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class disablecol001a { + + // name for the tested thread + public static final String OBJECT_FIELD_NAME = "object"; + + public static void main(String args[]) { + disablecol001a _disablecol001a = new disablecol001a(); + System.exit(disablecol001.JCK_STATUS_BASE + _disablecol001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.object = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + disablecol001.READY); + pipe.println(disablecol001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + disablecol001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(disablecol001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + disablecol001.QUIT + ")"); + log.display("Debugee FAILED"); + return disablecol001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return disablecol001.PASSED; + } + + // tested class + public static class TestedClass { + + // static field with the tested object value + public static volatile TestedClass object = null; + + private int foo = 0; + + public TestedClass() { + foo = 100; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.EnableCollection; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.EnableCollection. + * + * See enablecol001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class enablecol001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.EnableCollection"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "enablecol001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.EnableCollection"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.EnableCollection; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String OBJECT_FIELD_NAME = enablecol001a.OBJECT_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new enablecol001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debuggee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // query debuggee to disable garbage collection for this object + log.display("Disabling garbage collection for objectID: " + objectID); + disableObjectCollection(objectID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void disableObjectCollection(long objectID) { + CommandPacket command = new CommandPacket(JDWP.Command.ObjectReference.DisableCollection); + command.addObjectID(objectID); + ReplyPacket reply = debugee.receiveReplyFor(command); + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long objectID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/EnableCollection/enablecol001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: EnableCollection + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: enablecol001 + * debuggee: enablecol001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for the tested class + * and objectID as the value of the class static field. Debugger + * queries debuggee to disable garbage collection for this object. + * Then, debugger creates command packet for ObjectReference.EnableCollection + * command with the found objectID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks that there is no reply data in the package. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.EnableCollection.enablecol001 + * nsk.jdwp.ObjectReference.EnableCollection.enablecol001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.EnableCollection.enablecol001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.EnableCollection; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class enablecol001a { + + // name for the tested thread + public static final String OBJECT_FIELD_NAME = "object"; + + public static void main(String args[]) { + enablecol001a _enablecol001a = new enablecol001a(); + System.exit(enablecol001.JCK_STATUS_BASE + _enablecol001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.object = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + enablecol001.READY); + pipe.println(enablecol001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + enablecol001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(enablecol001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + enablecol001.QUIT + ")"); + log.display("Debugee FAILED"); + return enablecol001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return enablecol001.PASSED; + } + + // tested class + public static class TestedClass { + + // static field with the tested object value + public static volatile TestedClass object = null; + + private int foo = 0; + + public TestedClass() { + foo = 100; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.GetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.GetValues. + * + * See getvalues001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class getvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.GetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "getvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.GetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.GetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the static field in the tested class with the tested object value + static final String OBJECT_FIELD_NAME = getvalues001a.OBJECT_FIELD_NAME; + + // names and expected values of the tested fields + static final Object fields [][] = { + { "booleanValue", "boolean", new Boolean(true), "own"}, + { "byteValue", "byte", new Byte((byte)0x0F), "own"}, + { "charValue", "char", new Character('Z'), "own"}, + { "intValue", "int", new Integer(100), "own"}, + { "shortValue", "short", new Short((short)10), "own"}, + { "longValue", "long", new Long((long)1000000), "own"}, + { "floatValue", "float", new Float((float)3.14), "own"}, + { "doubleValue", "double", new Double((double)2.8e-12), "own"}, + { "objectValue", "objectID", new Long((long)0), "own"}, + + }; + static final int FIELDS_COUNT = fields.length; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new getvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // query debugee for fieldIDs of tested class static fields + log.display("Getting fieldIDs the tested class with the tested values"); + long fieldIDs[] = queryClassFieldIDs(classID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectID, fieldIDs); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Query debugee for fieldIDs and them into nested_classesIDs array. + */ + long[] queryClassFieldIDs(long typeID) { + // create array for expected filedIDs + long fieldIDs[] = new long[FIELDS_COUNT]; + for (int i = 0; i < FIELDS_COUNT; i++) { + fieldIDs[i] = 0; + } + + // obtain requested fieldIDs form debuggee + int count = 0; + try { + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(typeID); + command.setLength(); + + ReplyPacket reply = debugee.receiveReplyFor(command); + reply.resetPosition(); + + long declared = reply.getInt(); + if (declared < FIELDS_COUNT) { + throw new Failure("Too few fields of the tested class returned: " + declared + + " (expected: at least " + FIELDS_COUNT + ")"); + } + + for (int i = 0; i < declared; i++ ) { + long fieldID = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + for (int j = 0; j < FIELDS_COUNT; j++) { + if (fields[j][0].equals(name)) { + fieldIDs[j] = fieldID; + break; + } + } + } + + if (!reply.isParsed()) { + throw new Failure("Extra trailing bytes found in the reply packet at: " + + reply.currentPosition()); + } + + } catch (BoundException e) { + throw new Failure("Unable to extract field IDs from the reply packet:\n" + + e.getMessage()); + } + + return fieldIDs; + } + + /** + * Extract and check i-th value from the reply packet. + */ + void checkValue(int i, JDWP.Value value) { + if (!fields[i][2].equals(value.getValue())) { + log.complain("Unexpected value for " + i + " field received: " + value + + " (expected: " + fields[i][2] + ")"); + success = false; + } + } + + /** + * Perform testing JDWP command for specified objectID. + */ + void testCommand(long objectID, long fieldIDs[]) { + int count = fieldIDs.length; + + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + log.display(" fields: " + count); + command.addInt(count); + for (int i = 0; i < count; i++) { + log.display(" #" + i +": fieldID: " + fieldIDs[i]); + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check number of values + int values = 0; + try { + values = reply.getInt(); + log.display(" values: " + values); + + } catch (BoundException e) { + log.complain("Unable to extract number of values form reply packet:\n" + e.getMessage()); + success = false; + } + + // check if number of values are as expected + if (values < 0) { + log.complain("Negative number of values received:" + values + + " (expected: " + count + ")"); + success = false; + } else if (values != count) { + log.complain("Unexpected number of values received:" + values + + " (expected: " + count + ")"); + success = false; + } + + // extract and check each value + for (int i = 0; i < values; i++ ) { + log.display(" value #" + i + " (field: " + fields[i][0] + ")"); + + // extract value + JDWP.Value value = null; + try { + value = reply.getValue(); + log.display(" value: " + value); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " value:\n" + e.getMessage()); + success = false; + break; + } + + // extract and check value by known type tag + checkValue(i, value); + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/GetValues/getvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: GetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the returned values of requested fields are equal to + * the expected ones. + * Test consists of two compoments: + * debugger: getvalues001 + * debuggee: getvalues001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains from debuggee classID for the tested class and + * objectID as the value of the class static field. Also debugger obtains + * fieldIDs for all tested fields of the class. + * Then, debugger creates command packet for GetValues command with the + * found objectID and list of fieldIDs as arguments, writes packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts values of the requested fields. Also test checks + * that extracted values are equal to the expected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.GetValues.getvalues001 + * nsk.jdwp.ObjectReference.GetValues.getvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.GetValues.getvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.GetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class getvalues001a { + + public static final String OBJECT_FIELD_NAME = "object"; + + public static void main(String args[]) { + getvalues001a _getvalues001a = new getvalues001a(); + System.exit(getvalues001.JCK_STATUS_BASE + _getvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass.object = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + getvalues001.READY); + pipe.println(getvalues001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + getvalues001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(getvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + getvalues001.QUIT + ")"); + log.display("Debugee FAILED"); + return getvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return getvalues001.PASSED; + } + + // tested class with own static fields values + public static class TestedClass { + + // static field with tested object + public static TestedClass object = null; + + // fields with tested values + private boolean booleanValue = true; + private final byte byteValue = (byte)0x0F; + protected char charValue = 'Z'; + protected final int intValue = 100; + public short shortValue = (short)10; + public final long longValue = (long)1000000; + float floatValue = (float)3.14; + final double doubleValue = (double)2.8e-12; + TestedClass objectValue = null; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.InvokeMethod; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.InvokeMethod. + * + * See invokemeth001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class invokemeth001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.InvokeMethod"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "invokemeth001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command + static final String JDWP_COMMAND_NAME = "ObjectReference.InvokeMethod"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.InvokeMethod; + + // tested class name and signature + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // field and method names + static final String OBJECT_FIELD_NAME = "object"; + static final String RESULT_FIELD_NAME = "result"; + static final String TESTED_METHOD_NAME = "testedMethod"; + static final String BREAKPOINT_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE_NUMBER = invokemeth001a.BREAKPOINT_LINE_NUMBER; + + // data for invoked method + static final int ARGUMENTS_COUNT = 1; + static final int INITIAL_VALUE = invokemeth001a.INITIAL_VALUE; + static final int ARGUMENT_VALUE = invokemeth001a.FINAL_VALUE; + static final int RETURN_VALUE = INITIAL_VALUE; + static final int INVOKE_OPTIONS = 0; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + boolean dead = false; + + // data obtained from debuggee + long classID = 0; + long threadID = 0; + long methodID = 0; + long objectID = 0; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new invokemeth001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee VM"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debuggee launched"); + + // set timeout for debuggee responces + int waitTime = argumentHandler.getWaitTime(); // minutes + long timeout = waitTime * 60 * 1000; // milliseconds + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for VM_INIT event + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // run the test + runTest(); + + // wait for VM_DEATH event + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + log.display(" ... VM_DEATH event received"); + dead = true; + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + log.display("\n>>> Finishing test \n"); + + // disconnect debugee and wait for its exit + if (debugee != null) { + quitDebugee(); + } + } + + // check result + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + out.println("TEST PASSED"); + return PASSED; + } + + /** + * Obtain required data and test JDWP command. + */ + void runTest() { + log.display("\n>>> Obtaining required data \n"); + + // wait for tested class loaded on debuggee startup and obtain its classID + log.display("Waiting for class loaded:\n\t" + TESTED_CLASS_NAME); + classID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + classID); + log.display(""); + + // query debuggee for tested methodID + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + methodID); + log.display(""); + + // set breakpoint and wait for debugee reached it + log.display("Waiting for breakpoint reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_NUMBER); + threadID = debugee.waitForBreakpointReached(classID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE_NUMBER, + JDWP.SuspendPolicy.EVENT_THREAD); + log.display(" ... breakpoint reached with threadID: " + threadID); + log.display(""); + + // get object value from static field + log.display("Getting object value from static field: " + OBJECT_FIELD_NAME); + objectID = queryObjectID(classID, OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" ... got objectID: " + objectID); + + + // test JDWP command + log.display("\n>> Testing JDWP command \n"); + testCommand(); + + // check command results + if (success) { + log.display("\n>>> Checking command results \n"); + checkResult(); + } + + // resume debuggee after the command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" classID: " + classID); + command.addReferenceTypeID(classID); + log.display(" methodID: " + methodID); + command.addMethodID(methodID); + log.display(" arguments: " + ARGUMENTS_COUNT); + command.addInt(ARGUMENTS_COUNT); + for (int i = 0; i < ARGUMENTS_COUNT; i++) { + JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); + log.display(" arg: " + value); + command.addValue(value); + } + log.display(" options: " + INVOKE_OPTIONS); + command.addInt(INVOKE_OPTIONS); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet for tested command:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // extract return value + JDWP.Value returnValue = null; + try { + returnValue = reply.getValue(); + log.display(" returnValue: " + returnValue); + } catch (BoundException e) { + log.complain("Unable to extract returnValues from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract exception tag + JDWP.Value exception = null; + try { + exception = reply.getValue(); + log.display(" exception: " + exception); + } catch (BoundException e) { + log.complain("Unable to extract exception from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... packed data parsed"); + + // check that return value is an integer + if (returnValue.getTag() != JDWP.Tag.INT) { + log.complain("Unexpected tag of returnValue returned: " + returnValue.getTag() + + " (expected: " + JDWP.Tag.INT + ")"); + success = false; + } + + // check that return value is as expected + int intValue = ((Integer)returnValue.getValue()).intValue(); + if (intValue != RETURN_VALUE) { + log.complain("Unexpected value of returnValue returned: " + intValue + + " (expected: " + RETURN_VALUE + ")"); + success = false; + } + + // check that exception value is an object + if (exception.getTag() != JDWP.Tag.OBJECT) { + log.complain("Unexpected tag of exception returned: " + exception.getTag() + + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // check that exception object is null + long exceptionID = ((Long)exception.getValue()).longValue(); + if (exceptionID != 0) { + log.complain("Non-null exception object returned: " + exceptionID + + " (expected: " + 0 + ")"); + success = false; + } + } + + /** + * Check result of the tested JDWP command. + */ + void checkResult() { + // query debuggee for result value from a static field + log.display("Getting result value from static field: " + RESULT_FIELD_NAME); + int result = queryInt(classID, RESULT_FIELD_NAME, JDWP.Tag.INT); + log.display(" ... got result: " + result); + + // check if the result value is changed as expected + if (result != ARGUMENT_VALUE) { + log.complain("Method has not been really invoked: \n\t" + + "variable not changed by the method: " + result + + " (expected: " + ARGUMENT_VALUE + ")"); + success = false; + } else { + log.display("Method has been really invoked: \n\t" + + " variable changed by the method: " + result + + " (expected: " + ARGUMENT_VALUE + ")"); + } + } + + /** + * Query debuggee for value of static field of the class. + */ + JDWP.Value queryFieldValue(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + log.complain("unexpedted value tag returned from debuggee: " + value.getTag() + + " (expected: " + tag + ")"); + throw new Failure("Error occured while getting value from static field: " + + fieldName); + } + + return value; + } + + /** + * Query debuggee for objectID value of static field of the class. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + JDWP.Value value = queryFieldValue(classID, fieldName, tag); + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Query debuggee for int value of static field of the class. + */ + int queryInt(long classID, String fieldName, byte tag) { + JDWP.Value value = queryFieldValue(classID, fieldName, tag); + int intValue = ((Integer)value.getValue()).intValue(); + return intValue; + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debuggee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally dispose debuggee:\n\t" + e.getMessage()); + } + } + + // wait for debugee exits + log.display("Waiting for debuggee exits"); + int code = debugee.waitFor(); + log.display(" ... debuggee finished with exit code: " + code); + + // analize debuggee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: InvokeMethod + * Test checks that debugee accept the command packet and replies + * with correct reply packet. Also test checks that the tested method + * is really invoked for an object into debuggee. + * Test consists of two compoments: + * debugger: invokemeth001 + * debuggee: invokemeth001a + * First, debugger uses nsk.share.* support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded, requests methodID + * for tested method, sets breakpoint and wait for breakpoint reached. + * When breakpoint event received the tested thread into debuggee + * is suspended by this event. Debugger gets objectID value for tested + * object from static field of the tested class. + * Then, debugger creates command packet for ObjectReference.InvokeMethod + * command with the found objectID, classID, methodID, threadID, and also + * adds one integer argument for the method invocation. Then debugger writes + * packet to the transport channel and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts method's result value and exception objectID. Test checks + * if result value is an expected integer and exception objectID is null. + * Also test gets value of static field, wich should be modified by + * the invoked method, to verify if this method was really invoked + * into debuggee. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.InvokeMethod.invokemeth001 + * nsk.jdwp.ObjectReference.InvokeMethod.invokemeth001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.InvokeMethod.invokemeth001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.ObjectReference.InvokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class invokemeth001a { + + // name of the tested thread + public static final String THREAD_NAME = "testedThread"; + + // line nunber for breakpoint + public static final int BREAKPOINT_LINE_NUMBER = 90; + + // initial and final value of variable changed by the method invoked from debugger + public static final int INITIAL_VALUE = 10; + public static final int FINAL_VALUE = 1234; + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + invokemeth001a _invokemeth001a = new invokemeth001a(); + System.exit(invokemeth001.JCK_STATUS_BASE + _invokemeth001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested of tested class + log.display("Creating object of tested class"); + TestedObjectClass.object = new TestedObjectClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + TestedObjectClass.run(); + + log.display("Debugee PASSED"); + return invokemeth001.PASSED; + } + + // tested object class + public static class TestedObjectClass { + + // tested object value + public static volatile TestedObjectClass object = null; + + // result of invoking tested mathod + public static volatile int result = INITIAL_VALUE; + + // start the thread and suspend on breakpoint + public static void run() { + log.display("Tested thread: started"); + + log.display("Breakpoint line reached"); + // next line is for breakpoint + int foo = 0; // BREAKPOINT_LINE_NUMBER + log.display("Breakpoint line passed"); + + log.display("Tested thread: finished"); + } + + // tested method for invokation from debugger + public int testedMethod(int arg) { + log.display("Tested method invoked with argument:" + arg); + int old = result; + result = arg; + log.display("Tested method returned with result:" + old); + return old; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.IsCollected; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.IsCollected. + * + * See iscollected001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class iscollected001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.IsCollected"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "iscollected001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.IsCollected"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.IsCollected; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String OBJECT_FIELD_NAME = iscollected001a.OBJECT_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new iscollected001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debuggee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectID, classID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long objectID, long classID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract boolean result value + byte isCollected = (byte)0; + try { + isCollected = reply.getByte(); + log.display(" isCollected: " + isCollected); + } catch (BoundException e) { + log.complain("Unable to extract isCollected boolean value from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that isCollected is false (i.e. 0) + if (isCollected != 0) { + log.complain("Unexpected true isCollected value received:" + isCollected + + " (expected" + 0); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/IsCollected/iscollected001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: IsCollected + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that the returned isCollected value is false + * because tested object is not garbage collected into debuggee. + * Test consists of two compoments: + * debugger: iscollected001 + * debuggee: iscollected001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for the tested class + * and objectID as the value of the class static field. + * Then, debugger creates command packet for ObjectReference.IsCollected + * command with the found objectID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts isCollected boolean value. Also test checks that the + * extracted isCollected value is false. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.IsCollected.iscollected001 + * nsk.jdwp.ObjectReference.IsCollected.iscollected001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.IsCollected.iscollected001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.IsCollected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class iscollected001a { + + // name for the tested thread + public static final String OBJECT_FIELD_NAME = "object"; + + public static void main(String args[]) { + iscollected001a _iscollected001a = new iscollected001a(); + System.exit(iscollected001.JCK_STATUS_BASE + _iscollected001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.object = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + iscollected001.READY); + pipe.println(iscollected001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + iscollected001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(iscollected001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + iscollected001.QUIT + ")"); + log.display("Debugee FAILED"); + return iscollected001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return iscollected001.PASSED; + } + + // tested class + public static class TestedClass { + + // static field with the tested object value + public static volatile TestedClass object = null; + + private int foo = 0; + + public TestedClass() { + foo = 100; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.MonitorInfo; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.MonitorInfo. + * + * See monitorinfo001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class monitorinfo001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.MonitorInfo"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "monitorinfo001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_GET_MONITOR_INFO; + static final String VM_CAPABILITY_NAME = "canGetMonitorInfo"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.MonitorInfo"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.MonitorInfo; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = + DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = + "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String OBJECT_FIELD_NAME = + monitorinfo001a.OBJECT_FIELD_NAME; + static final String MONITOR_OWNER_FIELD_NAME = + monitorinfo001a.MONITOR_OWNER_FIELD_NAME; + static final String MONITOR_WAITER_FIELD_NAMES[] = + monitorinfo001a.MONITOR_WAITER_FIELD_NAMES; + + // threadIDs of threads owning or waiting for monitor of the tested object + long ownerThreadID = 0; + long waiterThreadIDs[] = null; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new monitorinfo001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Checking VM capability \n"); + + // check for VM capability + log.display("Checking VM capability: " + VM_CAPABILITY_NAME); + if (!debugee.getCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME)) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // query debuggee for threadIDs from static fields + queryThreadIDs(classID); + + log.display("\n>>> Testing JDWP command \n"); + + // suspend all threads into debuggee + log.display("Suspending all threads into debuggee"); + debugee.suspend(); + log.display(" debuggee suspended"); + + // perform testing JDWP command + testCommand(objectID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume all threads into debuggee + log.display("resuming all threads into debuggee"); + debugee.resume(); + log.display(" debuggee resumed"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested threads" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Query debuggee for threadID values of static class fields. + */ + void queryThreadIDs(long classID) { + + // get threadID for thread which ownes monitor of the tested object + ownerThreadID = queryObjectID(classID, MONITOR_OWNER_FIELD_NAME, JDWP.Tag.THREAD); + + // get threadIDs for threads which wait for monitor of the tested object + int count = MONITOR_WAITER_FIELD_NAMES.length; + waiterThreadIDs = new long[count]; + for (int i = 0; i < count; i++) { + waiterThreadIDs[i] = queryObjectID(classID, + MONITOR_WAITER_FIELD_NAMES[i], JDWP.Tag.THREAD); + } + } + + /** + * Perform testing JDWP command for specified objectID. + */ + void testCommand(long objectID) { + // make an array for results of found expected monitor waiters + int expectedWaiters = waiterThreadIDs.length; + int foundWaiters[] = new int[expectedWaiters]; + for (int i = 0; i < expectedWaiters; i++) { + foundWaiters[i] = 0; + } + + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract monitor owner threadID + long owner = 0; + try { + owner = reply.getObjectID(); + log.display(" owner: " + owner); + } catch (BoundException e) { + log.complain("Unable to extract monitor owner threadID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that monitor owner is as expected + if (owner < 0) { + log.complain("Negative value of monitor owner threadID received: " + + owner); + success = false; + } else if (owner == 0) { + log.complain("No monitor owner threadID received: " + + owner + " (expected: " + ownerThreadID + ")"); + success = false; + } else if (owner != ownerThreadID) { + log.complain("Unexpected monitor owner threadID received: " + + owner + " (expected: " + ownerThreadID + ")"); + success = false; + } + + // extract number of monitor entries + int entryCount = 0; + try { + entryCount = reply.getInt(); + log.display(" entryCount: " + entryCount); + } catch (BoundException e) { + log.complain("Unable to extract monitor entryCount from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that number of waiters is not negative and not zero + if (entryCount < 0) { + log.complain("Negative number of monitor entryCount received: " + + entryCount); + success = false; + } else if (entryCount == 0) { + log.complain("Zero number of monitor entryCount received: " + + entryCount); + success = false; + } + + // extract number of monitor waiter threads + int waiters = 0; + try { + waiters = reply.getInt(); + log.display(" waiters: " + waiters); + } catch (BoundException e) { + log.complain("Unable to extract number of monitor waiters from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that number of waiters is not negative + if (waiters < 0) { + log.complain("Negative number of monitor waiters received: " + + waiters); + success = false; + } + + // check that number of waiters is as expected + if (waiters != expectedWaiters) { + log.complain("Unexpected number of monitors waiters received: " + + waiters + " (expected: " + expectedWaiters + ")"); + success = false; + } + + // extract monitor waiter threadIDs + for (int i = 0; i < waiters; i++) { + + log.display(" waiter #" + i + ":"); + + // extract threadID + long threadID = 0; + try { + threadID = reply.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " monitor waiter threadID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // find threadID among expected monitor owner threadIDs + boolean found = false; + for (int j = 0; j < expectedWaiters; j++) { + if (threadID == waiterThreadIDs[j]) { + foundWaiters[j]++; + found = true; + } + } + if (!found) { + log.complain("Unexpected monitor waiter threadID received: " + threadID); + success = false; + } + + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check if all expected monitor waiter threadIDs found + for (int j = 0; j < expectedWaiters; j++) { + if (foundWaiters[j] <= 0) { + log.complain("Expected monitor waiter threadID NOT received: " + + waiterThreadIDs[j]); + success = false; + } else if (foundWaiters[j] > 1) { + log.complain("Expected monitor waiter threadID (" + + + waiterThreadIDs[j] + ") received multiply times: " + + foundWaiters[j]); + success = false; + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: MonitorInfo + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that expected threadIDs returned either for + * monitor owner and waiter threads. + * Test consists of two compoments: + * debugger: monitorinfo001 + * debuggee: monitorinfo001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Debuggee created oan object of the tested class as value of the class + * static field and starts several threads, which are waiting for this + * object monitor, and one thread, which ownes the object monitor. + * Then debuggee sends signal READY to the debugger. + * Debugger obtains from debuggee classID for tested class and objectID + * as the value of the class static field. Also debugger obtains threadIDs + * for all tested thread into debuggee. + * Debugger suspends debuggee (and all threads into it) before sending + * tested JDWP command. + * Then, debugger creates command packet for ObjectReference.MonitorInfo + * command with the found objectID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts threadIDs of thread waiting and owning the object monitor. + * Debugger checks that extracted threadIDs are equals to the expected ones.. + * Finally, debugger resumes debuggee, sends it signal to quit, waits + * for it exits and exits too with the proper exit code. + * COMMENTS + * For JDK 1.4.0-beta3 (build 1.4.0-beta3-b84) and earlier this test passed + * because target VM does not support VM capability: canGetMonitorInfo + * Test was fixed due to test bug: + * 4864492 TEST_BUG: potential race in JDWP test monitorinfo001 + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.MonitorInfo.monitorinfo001 + * nsk.jdwp.ObjectReference.MonitorInfo.monitorinfo001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.MonitorInfo.monitorinfo001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.MonitorInfo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class monitorinfo001a { + + // static field names for the tested objects + public static final String OBJECT_FIELD_NAME = "object"; + public static final String MONITOR_OWNER_FIELD_NAME = "monitorOwner"; + public static final String MONITOR_WAITER_FIELD_NAMES[] = + { "monitorWaiter1", "monitorWaiter2" }; + + // lock object to prevent thread from exit + private static Object threadExiting = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + monitorinfo001a _monitorinfo001a = new monitorinfo001a(); + System.exit(monitorinfo001.JCK_STATUS_BASE + _monitorinfo001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + // make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + long timeout = argumentHandler.getWaitTime() * 60 * 1000; + + boolean success = true; + + // lock the object to prevent threads from exit + synchronized (threadExiting) { + + // load tested class and create tested object and threads + log.display("Creating object of tested class and threads"); + TestedClass.object = new TestedClass(); + TestedClass.monitorOwner = new MonitorOwnerThread("MonitorOwnerThread"); + TestedClass.monitorWaiter1 = new MonitorWaiterThread("MonitorWaiterThread1"); + TestedClass.monitorWaiter2 = new MonitorWaiterThread("MonitorWaiterThread2"); + + // start MonitorWaiterThreads and wait for them become ready + if (success) { + if (!startMonitorWaiterThread(TestedClass.monitorWaiter1)) + success = false; + } + if (success) { + if (!startMonitorWaiterThread(TestedClass.monitorWaiter2)) + success = false; + } + + // start MonitorOwnerThread and wait for it becomes ready + if (success) { + if (!startMonitorOwnerThread(TestedClass.monitorOwner)) + success = false; + } + + // notify debugger if all threads started + if (success) { + log.display("Send signal to debugger: " + monitorinfo001.READY); + pipe.println(monitorinfo001.READY); + } else { + log.complain("Send signal to debugger: " + monitorinfo001.ERROR); + pipe.println(monitorinfo001.ERROR); + } + + if (success) { + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + monitorinfo001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(monitorinfo001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + monitorinfo001.QUIT + ")"); + success = false; + } + } + + // allow started threads to exit + } + + // finish monitor owner thread + finishThread(TestedClass.monitorOwner, timeout); + + // notify monitor waiting threads + synchronized (TestedClass.object) { + TestedClass.object.notifyAll(); + } + + // finish monitor waiting threads + finishThread(TestedClass.monitorWaiter2, timeout); + finishThread(TestedClass.monitorWaiter1, timeout); + + // exit debugee + if (!success) { + log.display("Debugee FAILED"); + return monitorinfo001.FAILED; + } + + log.display("Debugee PASSED"); + return monitorinfo001.PASSED; + } + + // start MonitorWaiterThread and waits for it becomes ready + private boolean startMonitorWaiterThread(MonitorWaiterThread thread) { + // start thread and wait for it becomes ready + synchronized (thread.ready) { + thread.start(); + try { + thread.ready.wait(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for MonitorWaiterThread started:\n\t" + + e); + return false; + } + } + + // ensure that thread becomes waiting for tested object + synchronized (TestedClass.object) { + return true; + } + } + + // start MonitorOwnrerThread and waits for it becomes ready + private boolean startMonitorOwnerThread(MonitorOwnerThread thread) { + // start thread an wait for it becomes ready + synchronized (thread.ready) { + thread.start(); + try { + thread.ready.wait(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for MonitorOwnerThread started:\n\t" + + e); + return false; + } + } + + return true; + } + + // interrupt thread if it is alive + private void finishThread(Thread thread, long timeout) { + try { + thread.join(timeout); + } catch (InterruptedException e) { + throw new Failure("Interruption while waiting for thread to finish:\n\t" + e); + } + + if (thread.isAlive()) { + log.display("Interrupting alive thread: " + thread.getName()); + thread.interrupt(); + } + } + + /////////////////// Tested class and threads //////////////// + + // tested thread class + public static class TestedClass { + + // field with the tested object value + public static volatile TestedClass object = null; + + // field with the thread which ownes monitor of the tested object + public static MonitorOwnerThread monitorOwner = null; + + // fields with the threads which wait for monitor of the tested object + public static MonitorWaiterThread monitorWaiter1 = null; + public static MonitorWaiterThread monitorWaiter2 = null; + + // internal field + private int foo = 0; + + // constructor + public TestedClass() { + foo = 100; + } + + } // TestedClass class + + // thread which will owns monitor of the tested object + public static class MonitorOwnerThread extends Thread { + + public Object ready = new Object(); + + public MonitorOwnerThread(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display(getName() + " started"); + + // get ownership for monitor of the tested object + synchronized (TestedClass.object) { + log.display(getName() + " owns monitor of the tested object"); + + // notify debuggee that thread is ready + synchronized (ready) { + ready.notifyAll(); + } + + // wait for debuggee releses object to finish threads + synchronized (threadExiting) { + log.display(getName() + " finished"); + } + + } + + } + + } // MonitorOwnerThreadClass + + // thread which will wait for monitor of the tested object + public static class MonitorWaiterThread extends Thread { + + public Object ready = new Object(); + + public MonitorWaiterThread(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display(getName() + " started"); + + // get ownership for object monitor for futher waiting + synchronized (TestedClass.object) { + + // notify debuggee that thread is ready + synchronized (ready) { + ready.notifyAll(); + } + + // go to the waiting state for monitor of the tested object + log.display(getName() + " waits for monitor of the tested object"); + try { + TestedClass.object.wait(); + } catch (InterruptedException e) { + log.display(getName() + " is interrupted while waiting for tested object"); + } + } + + // wait for debuggee releses object to finish threads + synchronized (threadExiting) { + log.display(getName() + " finished"); + } + + } + + } // MonitorWaiterThread class + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.ReferenceType; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.ReferenceType. + * + * See referencetype001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class referencetype001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.ReferenceType"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "referencetype001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.ReferenceType"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.ReferenceType; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String OBJECT_FIELD_NAME = referencetype001a.OBJECT_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new referencetype001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectID, classID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long objectID, long classID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract type tag + byte tag = (byte)0; + try { + tag = reply.getByte(); + log.display(" refTypeTag: " + tag); + } catch (BoundException e) { + log.complain("Unable to extract refTypeTag from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract typeID + long typeID = 0; + try { + typeID = reply.getReferenceTypeID(); + log.display(" typeID: " + typeID); + } catch (BoundException e) { + log.complain("Unable to extract referencTypeID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that tag is an CLASS type tag + if (tag != JDWP.TypeTag.CLASS) { + log.complain("Unexpected referenceTypetag received:" + tag + + " (expected" + JDWP.TypeTag.CLASS); + success = false; + } + + // check that typeID is not negative integer + if (typeID < 0) { + log.complain("Negative value of typeID received: " + typeID); + success = false; + } + + // check that typeID is equal to the expected classID + if (typeID != classID) { + log.display("Unexpected typeID received: " + typeID + + " (expected" + classID); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/ReferenceType/referencetype001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: ReferenceType + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that the returned referenceTypeID for the tested + * object is equals to the expected typeID of the tested class. + * Test consists of two compoments: + * debugger: referencetype001 + * debuggee: referencetype001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and objectID as the value of a class static field. + * thread is waiting for the object at this moment. + * Then, debugger creates command packet for ObjectReference.ReferenceType + * command with the found objectID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts typeTag and typeID for the requested object type. + * Also test checks that the extracted objectID is equals to the + * expected classID and typeTag is a CLASS type tag. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.ReferenceType.referencetype001 + * nsk.jdwp.ObjectReference.ReferenceType.referencetype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.ReferenceType.referencetype001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.ReferenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class referencetype001a { + + // name for the tested thread + public static final String OBJECT_FIELD_NAME = "object"; + + public static void main(String args[]) { + referencetype001a _referencetype001a = new referencetype001a(); + System.exit(referencetype001.JCK_STATUS_BASE + _referencetype001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.object = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + referencetype001.READY); + pipe.println(referencetype001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + referencetype001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(referencetype001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + referencetype001.QUIT + ")"); + log.display("Debugee FAILED"); + return referencetype001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return referencetype001.PASSED; + } + + // tested class + public static class TestedClass { + + // static field with the tested object value + public static volatile TestedClass object = null; + + private int foo = 0; + + public TestedClass() { + foo = 100; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: ReferringObjects + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: referringObjects001 + * debuggee: referringObjects001a + * Debuggee during startup initializes static field 'testInstance' with java.lang.Object instance + * and creates objects refer to this instance via references with types which should be supported + * by command ObjectReference.ReferringObjects: + * - strong reference + * - soft reference + * - weak reference + * - phantom reference + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * For maxReferrers in [1, 0, Interger.MAX_VALUE] + * do + * Debugger obtains objectID for instance assigned to the debuggee's static field 'testInstance'. + * Then, debugger creates command packet for ReferringObjects command with the + * found objectID and maxReferrers as an arguments, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of referring objects and referring objects ids. + * Debugger checks that received number of referring objects is correct: + * - if maxReferrers=1 only 1 referring object should be returned + * - if maxReferrers=0 or maxReferrers=Integer.MAX_VALUE all referring objects should be returned + * done + * Also, test performs checks for cases when incorrect data is sent in command. + * Following cases are tested: + * - create command with maxReferrers=-1, expect ILLEGAL_ARGUMENT error + * - create command with objectID = -1, expect INVALID_OBJECT error + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.ReferringObjects.referringObjects001.referringObjects001 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.ReferringObjects.referringObjects001.referringObjects001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ObjectReference.ReferringObjects.referringObjects001; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class referringObjects001 extends TestDebuggerType1 { + + protected String getDebugeeClassName() { + return nsk.jdwp.ObjectReference.ReferringObjects.referringObjects001.referringObjects001a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new referringObjects001().runIt(argv, out); + } + + private void testCommand(long objectID, int maxReferrers, int expectedReferrersCount, boolean expectError, int errorCode) { + try { + int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.ReferringObjects; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("objectID = " + objectID); + log.display("maxReferrers = " + maxReferrers); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(objectID); + command.addInt(maxReferrers); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command, expectError, errorCode); + + if (expectError) + return; + + int referringObjects = reply.getInt(); + log.display("referringObjects = " + referringObjects); + + // check that correct 'referringObjects' value was received + if (referringObjects != expectedReferrersCount) { + log.complain("Unexpected value 'referringObjects': " + referringObjects + " expected is " + expectedReferrersCount); + setSuccess(false); + } + + for (int i = 0; i < referringObjects; i++) { + JDWP.Value value = reply.getValue(); + log.display("tagged-ObjectID = " + value); + } + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + /* + * Provoke GC here to be sure that GC won't start during test execution + */ + forceGC(); + pipe.println(referringObjects001a.COMMAND_CREATE_TEST_INSTANCES); + + if (!isDebuggeeReady()) + return; + + + int referrersCount = referringObjects001a.expectedCount; + + long objectID = queryObjectID(debuggee.getReferenceTypeID(createTypeSignature(getDebugeeClassName())), "testInstance", JDWP.Tag.OBJECT); + + // create command with maxReferrers=1, only 1 referrer should be returned + testCommand(objectID, 1, 1, false, 0); + // create command with maxReferrers=0, all referrers should be returned + testCommand(objectID, 0, referrersCount, false, 0); + // create command with maxReferrers=Integer.MAX_VALUE, all referrers should be returned + testCommand(objectID, Integer.MAX_VALUE, referrersCount, false, 0); + + // create command with maxReferrers=-1, expect ILLEGAL_ARGUMENT error + testCommand(objectID, -1, referrersCount, true, JDWP.Error.ILLEGAL_ARGUMENT); + + // create command with objectID = -1, expect INVALID_OBJECT error + testCommand(-1, Integer.MAX_VALUE, referrersCount, true, JDWP.Error.INVALID_OBJECT); + + resetStatusIfGC(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ObjectReference.ReferringObjects.referringObjects001; + +import java.util.*; +import nsk.share.ReferringObjectSet; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdwp.*; + +public class referringObjects001a extends AbstractJDWPDebuggee { + public static Object testInstance; + + public static final String COMMAND_CREATE_TEST_INSTANCES = "COMMAND_CREATE_TEST_INSTANCES"; + + public static final int expectedCount = HeapwalkingDebuggee.includedIntoReferrersCountTypes.size() + 1; + + private ArrayList referrers = new ArrayList(); + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_CREATE_TEST_INSTANCES)) { + testInstance = new Object(); + + // create objects refering to 'testInstance' via references with types which should be supported by command ObjectReference.ReferringObjects + for (String referenceType : HeapwalkingDebuggee.includedIntoReferrersCountTypes) { + referrers.add(new ReferringObjectSet(testInstance, 1, referenceType)); + } + + return true; + } + + return false; + } + + public static void main(String args[]) { + new referringObjects001a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: ReferringObjects + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: referringObjects002 + * debuggee: referringObjects002a + * Debuggee contains static field 'testInstance' which initialized with java.lang.Object instance. + * Also debuggee contains 6 static fields with names referringObject1, ..., referringObject6, this fields + * are initialized with objects which refer to 'testInstance' and there are no more objects referring to + * the 'testInstance'. + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Debugger obtains objectID for instance assigned to the debuggee's static field 'testInstance'. + * Then, debugger creates command packet for ReferringObjects command with the + * found objectID and maxReferrers=0 as an arguments, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of referring objects and referring objects ids. + * Debugger checks that number of referring objects is correct - 6. + * Debugger obtains objectIDs for object instances stored in debuggee's fields referringObject1, ..., referringObject6 + * and checks that this values and referring objects ids received via JDWP command are identical. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.ReferringObjects.referringObjects002.referringObjects002 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.ReferringObjects.referringObjects002.referringObjects002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ObjectReference.ReferringObjects.referringObjects002; + +import java.io.PrintStream; +import nsk.share.Consts; +import nsk.share.jdwp.*; + +public class referringObjects002 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return nsk.jdwp.ObjectReference.ReferringObjects.referringObjects002.referringObjects002a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new referringObjects002().runIt(argv, out); + } + + private void testCommand() { + try { + int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.ReferringObjects; + + long objectID = queryObjectID( + debuggee.getReferenceTypeID(createTypeSignature(getDebugeeClassName())), + "testInstance", + JDWP.Tag.OBJECT); + + // create command with maxReferrers=0 (receive all referrers) + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("objectID = " + objectID); + log.display("maxReferrers = " + 0); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(objectID); + command.addInt(0); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command); + + int referringObjects = reply.getInt(); + log.display("referringObjects = " + referringObjects); + + // there are 6 referrers in debuggee + int expectedReferrersCount = 6; + + if (referringObjects != expectedReferrersCount) { + log.complain("Unexpected value 'referringObjects': " + referringObjects + " expected is " + expectedReferrersCount); + setSuccess(false); + } + + long expectedReferrersID[] = new long[expectedReferrersCount]; + + // initialize expected IDs of referrers + for (int i = 0; i < expectedReferrersCount; i++) { + expectedReferrersID[i] = queryObjectID(debuggee.getReferenceTypeID(createTypeSignature(getDebugeeClassName())), "referringObject" + + (i + 1)); + } + + long receivedReferrersID[] = new long[referringObjects]; + + for (int i = 0; i < referringObjects; i++) { + JDWP.Value value = reply.getValue(); + log.display("tagged-ObjectID = " + value); + + receivedReferrersID[i] = ((Long) value.getValue()).longValue(); + } + + // check that correct IDs of referrers was received + for (int i = 0; i < referringObjects; i++) { + boolean isIDExpected = false; + + for (int j = 0; j < expectedReferrersID.length; j++) { + if (receivedReferrersID[i] == expectedReferrersID[j]) { + isIDExpected = true; + break; + } + } + + if (!isIDExpected) { + setSuccess(false); + log.complain("Unexpected 'referrerID' value: " + receivedReferrersID[i]); + } + } + + if (!getSuccess()) { + log.complain("Expected IDs:"); + for (int i = 0; i < expectedReferrersID.length; i++) + log.complain("" + expectedReferrersID[i]); + } + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + testCommand(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ObjectReference.ReferringObjects.referringObjects002; + +import nsk.share.ObjectInstancesManager; +import nsk.share.ReferringObject; +import nsk.share.jdwp.*; + +public class referringObjects002a extends AbstractJDWPDebuggee { + public static Object testInstance = new Object(); + + // create 5 referrers for 'testInstance' + public static ReferringObject referringObject1 = new ReferringObject(testInstance, ObjectInstancesManager.STRONG_REFERENCE); + + public static ReferringObject referringObject2 = new ReferringObject(testInstance, ObjectInstancesManager.STRONG_REFERENCE); + + public static ReferringObject referringObject3 = new ReferringObject(testInstance, ObjectInstancesManager.STRONG_REFERENCE); + + public static ReferringObject referringObject4 = new ReferringObject(testInstance, ObjectInstancesManager.STRONG_REFERENCE); + + public static ReferringObject referringObject5 = new ReferringObject(testInstance, ObjectInstancesManager.STRONG_REFERENCE); + + // since 'testInstance' is static field one of the referrers is referringObjects002a.class + public static Class referringObject6 = referringObjects002a.class; + + public static void main(String args[]) { + new referringObjects002a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.SetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ObjectReference.SetValues. + * + * See setvalues001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class setvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String RUN = "run"; + static final String DONE = "done"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ObjectReference.SetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "setvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ObjectReference.SetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ObjectReference.SetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // target values class name and signature constants + static final String TARGET_VALUES_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TargetValuesClass"; + static final String TARGET_VALUES_CLASS_SIGNATURE = "L" + TARGET_VALUES_CLASS_NAME.replace('.', '/') + ";"; + + // name and siagnature of a class with static field with the tested object value + static final String OBJECT_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "ObjectClass"; + static final String OBJECT_CLASS_SIGNATURE = "L" + OBJECT_CLASS_NAME.replace('.', '/') + ";"; + + // name of the static field in the tested class with the tested object value + static final String OBJECT_FIELD_NAME = setvalues001a.OBJECT_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new setvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for classID for the class with target values + log.display("Getting classID for class with target values by signature:\n" + + " " + TARGET_VALUES_CLASS_SIGNATURE); + long targetValuesClassID = + debugee.getReferenceTypeID(TARGET_VALUES_CLASS_SIGNATURE); + log.display(" got classID: " + targetValuesClassID); + + // query debugee for fieldIDs of the class static fields + log.display("Getting fieldIDs for static fields of the class"); + long targetValuesFieldIDs[] = queryClassFieldIDs(targetValuesClassID); + log.display(" got fields: " + targetValuesFieldIDs.length); + int count = targetValuesFieldIDs.length; + + // query debugee for values of the fields + log.display("Getting values of the static fields"); + JDWP.Value targetValues[] = + queryClassFieldValues(targetValuesClassID, targetValuesFieldIDs); + log.display(" got values: " + targetValues.length); + if (targetValues.length != count) { + throw new Failure("Unexpected number of static fields values received: " + + targetValues.length + "(expected: " + count + ")"); + } + + // query debugee for classID of the tested class + log.display("Getting tested classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long testedClassID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + testedClassID); + + // query debugee for fieldIDs of tested class fields + log.display("Getting fieldIDs for tested fields of the tested class"); + long testedFieldIDs[] = queryClassFieldIDs(testedClassID); + log.display(" got fields: " + testedFieldIDs.length); + if (testedFieldIDs.length != count) { + throw new Failure("Unexpected number of fields of tested class received: " + + testedFieldIDs.length + "(expected: " + count + ")"); + } + + // query debugee for classID of the object class + log.display("Getting object classID by signature:\n" + + " " + OBJECT_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(OBJECT_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, + OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectID, testedFieldIDs, targetValues); + + // check confirmation from debuggee that values have been set properly + log.display("\n>>> Checking that the values have been set properly \n"); + checkValuesChanged(); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debugee for fieldID's of the class static fields. + */ + long[] queryClassFieldIDs(long classID) { + // compose ReferenceType.Fields command packet + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(classID); + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract fieldIDs from the reply packet + try { + reply.resetPosition(); + + int declared = reply.getInt(); + long[] fieldIDs = new long[declared]; + + int j = 0; + for (int i = 0; i < declared; i++ ) { + long fieldID = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + fieldIDs[i] = fieldID; + } + return fieldIDs; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.Fields command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fieldIDs for classID: " + classID); + } + } + + /** + * Query debugee for values of the class fields. + */ + JDWP.Value[] queryClassFieldValues(long classID, long fieldIDs[]) { + // compose ReferenceType.Fields command packet + int count = fieldIDs.length; + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.GetValues); + command.addReferenceTypeID(classID); + command.addInt(count); + for (int i = 0; i < count; i++) { + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract values from the reply packet + try { + reply.resetPosition(); + + int valuesCount = reply.getInt(); + JDWP.Value values[] = new JDWP.Value[valuesCount]; + for (int i = 0; i < valuesCount; i++ ) { + JDWP.Value value = reply.getValue(); + values[i] = value; + } + return values; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.GetValues command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fields values for classID: " + classID); + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified classID. + */ + void testCommand(long objectID, long fieldIDs[], JDWP.Value values[]) { + int count = fieldIDs.length; + + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" objectID: " + objectID); + command.addObjectID(objectID); + log.display(" values: " + count); + command.addInt(count); + for (int i = 0; i < count; i++) { + log.display(" field #" + i +":"); + log.display(" fieldID: " + fieldIDs[i]); + command.addFieldID(fieldIDs[i]); + + JDWP.Value value = values[i]; + JDWP.UntaggedValue untaggedValue = + new JDWP.UntaggedValue(value.getValue()); + log.display(" untagged_value: " + untaggedValue.getValue()); + command.addUntaggedValue(untaggedValue, value.getTag()); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no data to extract + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + + /** + * Check confiramtion from debuggee that values are changed. + */ + void checkValuesChanged() { + // send debugee signal RUN + log.display("Sending signal to debugee: " + RUN); + pipe.println(RUN); + + // wait for DONE signal from debugee + log.display("Waiting for signal from debugee: " + DONE); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + // check received signal + if (signal == null) { + throw new TestBug(" signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } else if (signal.equals(DONE)) { + log.display("All fields values have been correctly set into debuggee VM"); + } else if (signal.equals(ERROR)) { + log.complain("Not all fields values have been correctly set into debuggee VM"); + success = false; + } else { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ObjectReference/SetValues/setvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ObjectReference + * command: SetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the values are correctly set to debuggee class fields. + * Test consists of two compoments: + * debugger: setvalues001 + * debuggee: setvalues001a + * To set values to the static fields of the tested class + * and check that they are set correctly, test defines + * following classes into debuggee VM: + * OriginalValuesClass - class with original values of static fields + * TargetValuesClass - class with target values of static fields + * TestedClass - tested class with tested fields to set values to + * ObjectClass - class with one static field for the tested object + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains classIDs for the tested class and class with + * the target values from debugee. It obtains also fieldIDs for thess + * classese and target values of the fields. It obtains also objectID + * as the value of a static field of the object class. + * Then, debugger creates command packet for SetValues command with the + * found objectID and list of fieldIDs as arguments, writes packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and and checks that there is no data in the reply packet. + * Then debugger sends signal RUN to debuggee to ask it to verify + * new fields values of tested class. Debuggee compares these values + * with the original and target values and sends ERROR signal + * to debugger if the values was not set correctly. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ObjectReference.SetValues.setvalues001 + * nsk.jdwp.ObjectReference.SetValues.setvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ObjectReference.SetValues.setvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ObjectReference.SetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part of the test. + */ +public class setvalues001a { + + public static final String OBJECT_FIELD_NAME = "object"; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + setvalues001a _setvalues001a = new setvalues001a(); + System.exit(setvalues001.JCK_STATUS_BASE + _setvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + // make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of all required classes"); + OriginalValuesClass original = new OriginalValuesClass(); + TargetValuesClass target = new TargetValuesClass(); + ObjectClass.object = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + setvalues001.READY); + pipe.println(setvalues001.READY); + + // wait for signal RUN from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.RUN); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + // check received signal + if (signal == null || !signal.equals(setvalues001.RUN)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.RUN + ")"); + log.display("Debugee FAILED"); + return setvalues001.FAILED; + } + + // check assigned values + if (checkValues(ObjectClass.object)) { + log.display("Sending signal to debugger: " + setvalues001.DONE); + pipe.println(setvalues001.DONE); + } else { + log.display("Sending signal to debugger: " + setvalues001.ERROR); + pipe.println(setvalues001.ERROR); + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.QUIT); + signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + // check received signal + if (! signal.equals(setvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.QUIT + ")"); + log.display("Debugee FAILED"); + return setvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return setvalues001.PASSED; + } + + // check values of static fields for both classes + static boolean checkValues(TestedClass object) { + int different = 0; + log.display("Checking that values have been set correctly:"); + + // check value of the field + if (object.booleanValue != TargetValuesClass.booleanValue) { + different++; + log.complain(" booleanValue = " + object.booleanValue + "\n" + + " setting: " + OriginalValuesClass.booleanValue + + " -> " + TargetValuesClass.booleanValue); + if (object.booleanValue == OriginalValuesClass.booleanValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" booleanValue: " + OriginalValuesClass.booleanValue + + " -> " + TargetValuesClass.booleanValue); + } + + // check value of the field + if (object.byteValue != TargetValuesClass.byteValue) { + different++; + log.complain(" byteValue = " + object.byteValue + "\n" + + " setting: " + OriginalValuesClass.byteValue + + " -> " + TargetValuesClass.byteValue); + if (object.byteValue == OriginalValuesClass.byteValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" byteValue: " + OriginalValuesClass.byteValue + + " -> " + TargetValuesClass.byteValue); + } + + // check value of the field + if (object.charValue != TargetValuesClass.charValue) { + different++; + log.complain(" charValue = " + object.charValue + "\n" + + " setting: " + OriginalValuesClass.charValue + + " -> " + TargetValuesClass.charValue); + if (object.charValue == OriginalValuesClass.charValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" charValue: " + OriginalValuesClass.charValue + + " -> " + TargetValuesClass.charValue); + } + + // check value of the field + if (object.intValue != TargetValuesClass.intValue) { + different++; + log.complain(" intValue = " + object.intValue + "\n" + + " setting: " + OriginalValuesClass.intValue + + " -> " + TargetValuesClass.intValue); + if (object.intValue == OriginalValuesClass.intValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" intValue: " + OriginalValuesClass.intValue + + " -> " + TargetValuesClass.intValue); + } + + // check value of the field + if (object.shortValue != TargetValuesClass.shortValue) { + different++; + log.complain(" shortValue = " + object.shortValue + "\n" + + " setting: " + OriginalValuesClass.shortValue + + " -> " + TargetValuesClass.shortValue); + if (object.shortValue == OriginalValuesClass.shortValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" shortValue: " + OriginalValuesClass.shortValue + + " -> " + TargetValuesClass.shortValue); + } + + // check value of the field + if (object.longValue != TargetValuesClass.longValue) { + different++; + log.complain(" longValue = " + object.longValue + "\n" + + " setting: " + OriginalValuesClass.longValue + + " -> " + TargetValuesClass.longValue); + if (object.longValue == OriginalValuesClass.longValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" longValue: " + OriginalValuesClass.longValue + + " -> " + TargetValuesClass.longValue); + } + + // check value of the field + if (object.floatValue != TargetValuesClass.floatValue) { + different++; + log.complain(" floatValue = " + object.floatValue + "\n" + + " setting: " + OriginalValuesClass.floatValue + + " -> " + TargetValuesClass.floatValue); + if (object.floatValue == OriginalValuesClass.floatValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" floatValue: " + OriginalValuesClass.floatValue + + " -> " + TargetValuesClass.floatValue); + } + + // check value of the field + if (object.doubleValue != TargetValuesClass.doubleValue) { + different++; + log.complain(" doubleValue = " + object.doubleValue + "\n" + + " setting: " + OriginalValuesClass.doubleValue + + " -> " + TargetValuesClass.doubleValue); + if (object.doubleValue == OriginalValuesClass.doubleValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" doubleValue: " + OriginalValuesClass.doubleValue + + " -> " + TargetValuesClass.doubleValue); + } + + // check value of the field + if (object.stringValue != TargetValuesClass.stringValue) { + different++; + log.complain(" stringValue = " + object.stringValue + "\n" + + " setting: " + OriginalValuesClass.stringValue + + " -> " + TargetValuesClass.stringValue); + if (object.stringValue == OriginalValuesClass.stringValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" stringValue: " + OriginalValuesClass.stringValue + + " -> " + TargetValuesClass.stringValue); + } + + // check value of the field + if (object.objectValue != TargetValuesClass.objectValue) { + different++; + log.complain(" objectValue = " + object.objectValue + "\n" + + " setting: " + OriginalValuesClass.objectValue + + " -> " + TargetValuesClass.objectValue); + if (object.objectValue == OriginalValuesClass.objectValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" objectValue: " + OriginalValuesClass.objectValue + + " -> " + TargetValuesClass.objectValue); + } + +/* + // check value of the field + if (object.Value != TargetValuesClass.Value) { + different++; + log.complain(" Value = " + object.Value + "\n" + + " setting: " + OriginalValuesClass.Value + + " -> " + TargetValuesClass.Value); + if (object.Value == OriginalValuesClass.Value) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" Value: " + OriginalValuesClass.Value + + " -> " + TargetValuesClass.Value); + } +*/ + + // check taht no any changed value differs from target + if (different > 0) { + log.complain("Values of " + different + " fields have not been set correctly"); + return false; + } + + log.display("Values of all fields have been set correctly"); + return true; + } + + // class with the original values of static fields + public static class OriginalValuesClass { + static final boolean booleanValue = true; + static final byte byteValue = (byte)0x01; + static final char charValue = 'Z'; + static final int intValue = 100; + static final short shortValue = (short)10; + static final long longValue = (long)1000000; + static final float floatValue = (float)3.14; + static final double doubleValue = (double)2.8e-12; + static final String stringValue = "text"; + static final Object objectValue = new OriginalValuesClass(); + } + + // class with the original values of static fields + public static class TargetValuesClass { + static final boolean booleanValue = false; + static final byte byteValue = (byte)0x0F; + static final char charValue = 'A'; + static final int intValue = 999; + static final short shortValue = (short)88; + static final long longValue = (long)11111111; + static final float floatValue = (float)7.19; + static final double doubleValue = (double)4.6e24; + static final String stringValue = "new text"; + static final Object objectValue = new TargetValuesClass(); + } + + // tested class with own static fields values + public static class TestedClass { + private boolean booleanValue = OriginalValuesClass.booleanValue; + private byte byteValue = OriginalValuesClass.byteValue; + protected char charValue = OriginalValuesClass.charValue; + protected int intValue = OriginalValuesClass.intValue; + public short shortValue = OriginalValuesClass.shortValue; + public long longValue = OriginalValuesClass.longValue; + float floatValue = OriginalValuesClass.floatValue; + double doubleValue = OriginalValuesClass.doubleValue; + String stringValue = OriginalValuesClass.stringValue; + Object objectValue = OriginalValuesClass.objectValue; + } + + // class with static field with the tested object + public static class ObjectClass { + // static field with the tested object + public static TestedClass object = null; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.ClassLoader; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class classloader001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.ClassLoader"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "classloader001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.ClassLoader"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.ClassLoader; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new classloader001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long classLoaderID = reply.getObjectID(); + log.display(" classLoaderID: " + classLoaderID); + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while connecting to debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/ClassLoader/classloader001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: ClassLoader + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: classloader001 + * debuggee: classloader001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class, which + * will be used to test JDWP command. + * Then, debugger creates command packet for ClassLoader command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts classLoaderID. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.ClassLoader.classloader001 + * nsk.jdwp.ReferenceType.ClassLoader.classloader001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.ClassLoader.classloader001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.ClassLoader; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class classloader001a { + + public static void main(String args[]) { + classloader001a _classloader001a = new classloader001a(); + System.exit(classloader001.JCK_STATUS_BASE + _classloader001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return classloader001.PASSED; + } + + static public class TestedClass { + int foo = 0; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.ClassObject; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class classobj001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.ClassObject"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "classobj001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.ClassObject"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.ClassObject; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new classobj001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long classObjectID = reply.getObjectID(); + log.display(" classObjectID: " + classObjectID); + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + + } finally { + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while connecting to debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/ClassObject/classobj001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: ClassObject + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: classobj001 + * debuggee: classobj001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class, which + * will be used to test JDWP command. + * Then, debugger creates command packet for ClassObject command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts classObjectID. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.ClassObject.classobj001 + * nsk.jdwp.ReferenceType.ClassObject.classobj001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.ClassObject.classobj001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.ClassObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class classobj001a { + + public static void main(String args[]) { + classobj001a _classobj001a = new classobj001a(); + System.exit(classobj001.JCK_STATUS_BASE + _classobj001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return classobj001.PASSED; + } + + static public class TestedClass { + int foo = 0; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Fields; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class fields001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.Fields"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "fields001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.Fields"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Fields; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + static final String[][] fields = { + {"byteField", "B"}, + {"booleanField", "Z"}, + {"charField", "C"}, + {"shortField", "S"}, + {"intField", "I"}, + {"longField", "J"}, + {"floatField", "F"}, + {"doubleField", "D"}, + {"stringField", "Ljava/lang/String;"}, + {"objectField", TESTED_CLASS_SIGNATURE}, + {"intArrayField", "[I"} + }; + static final int DECLARED_FIELDS = fields.length; + static final int FIELD_MODIFIER_FLAGS = JDWP.ModifierFlag.PUBLIC; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new fields001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long declared = reply.getInt(); + log.display(" declared: " + declared); + + if (declared != DECLARED_FIELDS) { + log.complain("Unexpected number of declared fields in the reply packet :" + declared + + " (expected: " + DECLARED_FIELDS + ")"); + success = false; + } + + for (int i = 0; i < declared; i++ ) { + + log.display(" field #" + i); + + long fieldID = reply.getFieldID(); + log.display(" fieldID: " + fieldID); + + String name = reply.getString(); + log.display(" name: " + name); + if (! name.equals(fields[i][0])) { + log.complain("Unexpected name of field #" + i + " in the reply packet: " + name + + " (expected: " + fields[i][0] + ")"); + success = false; + } + + String signature = reply.getString(); + log.display(" signature: " + signature); + if (! signature.equals(fields[i][1])) { + log.complain("Unexpected type signature of field #" + i + " in the reply packet: " + signature + + " (expected: " + fields[i][1] + ")"); + success = false; + } + + int modBits = reply.getInt(); + String modBitsString = "0x" + Packet.toHexString(modBits, 8); + log.display(" modBits: " + modBitsString); + modBits &= JDWP.ModifierFlag.FIELD_MASK; + if (modBits != FIELD_MODIFIER_FLAGS) { + String expectedModBitsString = "0x" + Packet.toHexString(FIELD_MODIFIER_FLAGS, 8); + log.complain("Unexpected modifier flag of field #" + i + " in the reply packet: " + modBitsString + + " (expected: " + expectedModBitsString + ")"); + success = false; + } + + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/Fields/fields001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Fields + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * reply contains expected set of fields. + * Test consists of two compoments: + * debugger: fields001 + * debuggee: fields001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class, which + * will be used to test JDWP command. + * Then, debugger creates command packet for Fields command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts fields info. Test checks that all fields are equal to + * expected. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Fields.fields001 + * nsk.jdwp.ReferenceType.Fields.fields001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Fields.fields001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class fields001a { + + public static void main(String args[]) { + fields001a _fields001a = new fields001a(); + System.exit(fields001.JCK_STATUS_BASE + _fields001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return fields001.PASSED; + } + + static class TestedClass { + public byte byteField = (byte) 0xEE; + public boolean booleanField = false; + public char charField = 'Z'; + public short shortField = 10; + public int intField = 100; + public long longField = 1000000; + public float floatField = (float) 3.14; + public double doubleField = 2.48e-10; + public String stringField = "stringFieldValue"; + public TestedClass objectField = this; + public int[] intArrayField = {intField}; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.FieldsWithGeneric; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * This test checks that the JDWP command FieldsWithGeneric + * from the ReferenceType command set returns generic signature + * information properly.
+ * Debuggee part of the test contains several tested fields. Some of them + * are generic including the inherited fields. Debugger part obtains + * information for each field in a reference type of a tested class. + * Proper generic signature should be returned for the generic fields, or + * an empty string for non-generic ones. Information for the inherited + * fields should not be returned. + */ +public class fldwithgeneric001 { + static final String DEBUGGEE_CLASS = + "nsk.jdwp.ReferenceType.FieldsWithGeneric.fldwithgeneric001t"; + static final String TESTED_CLASS_SIGNATURE = + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001a;"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.FieldsWithGeneric"; + static final int JDWP_COMMAND_ID = + JDWP.Command.ReferenceType.FieldsWithGeneric; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String[][] fields = { + {"_fldwithgeneric001St", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001;", + "NULL"}, + + {"_fldwithgeneric001b", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001b;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001b;"}, + {"_fldwithgeneric001bSt", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001b;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001b;"}, + + {"_fldwithgeneric001c", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001c;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001c;"}, + {"_fldwithgeneric001cSt", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001c;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001c;"}, + + {"_fldwithgeneric001e", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001e;", + "NULL"}, + {"_fldwithgeneric001eSt", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001e;", + "NULL"}, + + {"_fldwithgeneric001if", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001if;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001if;"}, + {"_fldwithgeneric001ifSt", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001if;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001if;"}, + + {"_fldwithgeneric001g", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001g;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001g;"}, + {"_fldwithgeneric001gSt", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001g;", + "Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001g;"}, + + {"_fldwithgeneric001gArr", + "[Lnsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001g;", + "NULL"} + }; + + static final int FLDS_NUM = fields.length; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new fldwithgeneric001().runThis(argv, out); + } + + public int runThis(String argv[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + boolean result = true; + + try { + Binder binder = new Binder(argumentHandler, log); + + log.display("Starting debuggee VM ..."); + Debugee debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + + Transport transport = debuggee.getTransport(); + IOPipe pipe = debuggee.createIOPipe(); + + log.display("Waiting for VM_INIT event ..."); + debuggee.waitForVMInit(); + + log.display("Querying for IDSizes ..."); + debuggee.queryForIDSizes(); + + log.display("Resuming debuggee VM ..."); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY + + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd); + + try { + long typeID = debuggee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + /////// begin test of JDWP command + log.display("\nCreate command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("\nWaiting for reply packet ..."); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display(" ... Reply packet received:\n" + reply); + + log.display("\nChecking reply packet header"); + reply.checkHeader(command.getPacketID()); + +/* parsing of reply data: + int declared - Number of declared fields + + ---- Repeated 'declared' times: + fieldID fieldID - Field ID + string nam - The name of the field + string signature - The JNI signature of the field. + string genericSignature - The generic signature of the field, + or an empty string if there is none. + int modBits - The modifier bit flags (also known as access flags) + ---- +*/ + log.display("\nParsing reply packet:"); + reply.resetPosition(); + + long declared = reply.getInt(); + log.display("\tdeclared: " + declared); + + if (declared != FLDS_NUM) { + log.complain("TEST FAILED: Unexpected number of declared fields in the reply packet:" + + "\n\tGot: " + declared + + "\n\tExpected: " + FLDS_NUM + "\n"); + result = false; + } + + for (int i=0; i>> field #" + i); + + long fieldID = reply.getFieldID(); + log.display("\t\tfieldID: " + fieldID); + + String name = reply.getString(); + log.display("\t\tname: " + name); + if (!name.equals(fields[i][0])) { + log.complain("TEST FAILED: Unexpected name of field #" + i + + " in the reply packet:" + + "\n\tGot: " + name + + "\n\tExpected: " + fields[i][0] + "\n"); + result = false; + } + + String signature = reply.getString(); + log.display("\t\tsignature: " + signature); + if (!signature.equals(fields[i][1])) { + log.complain("TEST FAILED: Unexpected type signature of field #" + i + + " in the reply packet:" + + "\n\tGot: " + signature + + "\n\tExpected: " + fields[i][1] + "\n"); + result = false; + } + + String genSignature = reply.getString(); + log.display("\t\tgeneric signature: " + genSignature); + if (genSignature.length() == 0) // a non-generic field + genSignature = "NULL"; + if (!genSignature.equals(fields[i][2])) { + log.complain("TEST FAILED: Unexpected generic signature of field #" + i + + " in the reply packet:" + + "\n\tGot: " + genSignature + + "\n\tExpected: " + fields[i][2] + "\n"); + result = false; + } + + int modBits = reply.getInt(); + String modBitsString = "0x" + Packet.toHexString(modBits, 8); + log.display("\t\tmodBits: " + modBitsString); + } + + if (!reply.isParsed()) { + log.complain("TEST FAILED: Extra trailing bytes found in reply packet at: " + + reply.currentPosition()); + result = false; + } else + log.display("\nReply packet parsed"); + /////// end test of JDWP command + + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught exception while testing JDWP command: " + + e); + result = false; + } finally { + log.display("Sending command: " + COMMAND_QUIT + " ..."); + pipe.println(COMMAND_QUIT); + + log.display("Waiting for debuggee exits ..."); + int code = debuggee.waitFor(); + if (code == Consts.JCK_STATUS_BASE + Consts.TEST_PASSED) { + log.display(" ... Debuggee PASSED with the exit code: " + + code); + } else { + log.complain(" ... Debuggee FAILED with the exit code: " + + code); + result = false; + } + } + + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while communicating with debugee: " + + e); + result = false; + } + + if (!result) + return Consts.TEST_FAILED; + + return Consts.TEST_PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * JDWP command set: ReferenceType + * JDWP command: FieldsWithGeneric + * It checks that the command returns generic signature information + * properly. + * Debuggee part of the test contains several tested fields. Some of them + * are generic including the inherited fields. Debugger part obtains + * information for each field in a reference type of a tested class. + * Proper generic signature should be returned for the generic fields, or + * NULL for non-generic ones. Information for the inherited fields should + * not be returned. + * COMMENTS + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.FieldsWithGeneric.fldwithgeneric001 + * nsk.jdwp.ReferenceType.FieldsWithGeneric.fldwithgeneric001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.FieldsWithGeneric.fldwithgeneric001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001t.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001t.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.FieldsWithGeneric; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class fldwithgeneric001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + // load a tested class + fldwithgeneric001a _fldwithgeneric001a = + new fldwithgeneric001a(); + + log.display("Debuggee VM started\nSending command: " + + fldwithgeneric001.COMMAND_READY); + pipe.println(fldwithgeneric001.COMMAND_READY); + + log.display("Waiting for command: " + + fldwithgeneric001.COMMAND_QUIT + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd + + "\nDebuggee is exiting ..."); + + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } +} + +/* + * Dummy classes used only for verifying generic signature information + * in a debugger. + */ + +class fldwithgeneric001b {} + +class fldwithgeneric001c {} + +interface fldwithgeneric001if {} + +class fldwithgeneric001d implements fldwithgeneric001if {} + +class fldwithgeneric001e {} + +class fldwithgeneric001f extends fldwithgeneric001e implements fldwithgeneric001if {} + +class fldwithgeneric001g {} + +class fldwithgeneric001h { + // dummy fields to be inherited. They must not be included into + // information for reference type fields. + public fldwithgeneric001 _fldwithgeneric001h = + new fldwithgeneric001(); + public fldwithgeneric001b _fldwithgeneric001bh = + new fldwithgeneric001b(); +} + +class fldwithgeneric001a extends fldwithgeneric001h { + // dummy fields used for testing + public static fldwithgeneric001 _fldwithgeneric001St = + new fldwithgeneric001(); + fldwithgeneric001b _fldwithgeneric001b = + new fldwithgeneric001b(); + static fldwithgeneric001b _fldwithgeneric001bSt = + new fldwithgeneric001b(); + fldwithgeneric001c _fldwithgeneric001c = + new fldwithgeneric001c(); + static fldwithgeneric001c _fldwithgeneric001cSt = + new fldwithgeneric001c(); + fldwithgeneric001e _fldwithgeneric001e = + new fldwithgeneric001e(); + static fldwithgeneric001e _fldwithgeneric001eSt = + new fldwithgeneric001e(); + fldwithgeneric001if _fldwithgeneric001if = + new fldwithgeneric001d(); + static fldwithgeneric001if _fldwithgeneric001ifSt = + new fldwithgeneric001d(); + fldwithgeneric001g _fldwithgeneric001g = + new fldwithgeneric001g(); + static fldwithgeneric001g _fldwithgeneric001gSt = + new fldwithgeneric001g(); + fldwithgeneric001g[] _fldwithgeneric001gArr = + new fldwithgeneric001g[]{}; +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.GetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ReferenceType.GetValues. + * + * See getvalues001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class getvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.GetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "getvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ReferenceType.GetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.GetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // nested classes names and signatures array + static final Object fields [][] = { + { "booleanValue", "boolean", new Boolean(true), "own"}, + { "byteValue", "byte", new Byte((byte)0x0F), "own"}, + { "charValue", "char", new Character('Z'), "own"}, + { "intValue", "int", new Integer(100), "own"}, + { "shortValue", "short", new Short((short)10), "own"}, + { "longValue", "long", new Long((long)1000000), "own"}, + { "floatValue", "float", new Float((float)3.14), "own"}, + { "doubleValue", "double", new Double((double)2.8e-12), "own"}, + { "objectValue", "objectID", new Long((long)0), "own"}, + + }; + static final int FIELDS_COUNT = fields.length; + + // field ID's for tested class static fields + static final long[] fieldIDs = new long[FIELDS_COUNT]; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new getvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got TypeID: " + typeID); + + // query debugee for fieldIDs of tested class static fields + log.display("Getting fieldIDs for static fields of the tested class"); + queryClassFieldIDs(typeID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(typeID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + e.printStackTrace(out); + success = false; + } catch (Exception e) { + log.complain("Caught unexpected exception:\n" + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received form debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debugee for TypeIDs for nested classes from nested_classes array + * and put them into nested_classesIDs array. + */ + void queryClassFieldIDs(long typeID) { + for (int i = 0; i < FIELDS_COUNT; i++) { + fieldIDs[i] = 0; + } + + int count = 0; + try { + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(typeID); + command.setLength(); + + ReplyPacket reply = debugee.receiveReplyFor(command); + reply.resetPosition(); + + long declared = reply.getInt(); + log.display(" declared: " + declared); + + for (int i = 0; i < declared; i++ ) { + long fieldID = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + boolean found = false; + for (int j = 0; j < FIELDS_COUNT; j++) { + if (fields[j][0].equals(name)) { + if (fieldIDs[j] != 0) { + throw new Failure("Duplicated field name of the tested class returned: " + name); + } + fieldIDs[j] = fieldID; + found = true; + break; + } + } + if (!found) { + throw new Failure("Unexpected field of the tested class returned: " + name); + } + } + + if (declared < FIELDS_COUNT) { + throw new Failure("Too few fields of the tested class returned: " + declared + + " (expected: " + FIELDS_COUNT + ")"); + } + + if (declared > FIELDS_COUNT) { + throw new Failure("Too many fields of the tested class returned: " + declared + + " (expected: " + FIELDS_COUNT + ")"); + } + + if (!reply.isParsed()) { + throw new Failure("Extra trailing bytes found in the reply packet at: " + + reply.currentPosition()); + } + + } catch (BoundException e) { + throw new Failure("Unable to extract field IDs from the reply packet:\n" + + e.getMessage()); + } + } + + /** + * Extract and check i-th value from the reply packet. + */ + void checkValue(int i, JDWP.Value value) { + if (!fields[i][2].equals(value.getValue())) { + log.complain("Unexpected value for " + i + " field in reply packet: " + value + + " (expected value: " + fields[i][2] + ")"); + success = false; + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long typeID) { + // create command packet + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + // add out data to the command packet + log.display(" refType: " + typeID); + command.addReferenceTypeID(typeID); + log.display(" fields: " + FIELDS_COUNT); + command.addInt(FIELDS_COUNT); + for (int i = 0; i < FIELDS_COUNT; i++) { + log.display(" #" + i +": fieldID: " + fieldIDs[i]); + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet: " + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check number of values + int values = 0; + try { + values = reply.getInt(); + log.display(" values: " + values); + + if (values != FIELDS_COUNT) { + log.complain("Unexpected number of values in the reply packet:" + values + + " (expected: " + FIELDS_COUNT + ")"); + success = false; + } + } catch (BoundException e) { + log.complain("Unable to extract number of values form reply packet:\n" + e.getMessage()); + success = false; + } + + // extract and check TypeID for each nested class + for (int i = 0; i < values; i++ ) { + log.display(" value #" + i + " (field: " + fields[i][0] + ")"); + + // extract TypeTag byte + JDWP.Value value = null; + try { + value = reply.getValue(); + log.display(" value: " + value); + } catch (BoundException e) { + log.complain("Unable to extract type tag of " + i + " value:\n" + e.getMessage()); + success = false; + break; + } + + // extract and check value by known type tag + checkValue(i, value); + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/GetValues/getvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: GetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the returned values of requested fields are equal to + * the expected ones. + * Test consists of two compoments: + * debugger: getvalues001 + * debuggee: getvalues001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization messages. + * Next, debugger obtains ReferenceTypeIDs for the tested class from + * debugee, and obtains also fieldIDs for all tested fields of this class. + * Then, debugger creates command packet for GetValues command with the + * found referenceTypeID and list of fieldIDs as arguments, writes packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts values of the requested fields. Also test checks + * that extracted values are equal to the expected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.GetValues.getvalues001 + * nsk.jdwp.ReferenceType.GetValues.getvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.GetValues.getvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.GetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class getvalues001a { + + public static void main(String args[]) { + getvalues001a _getvalues001a = new getvalues001a(); + System.exit(getvalues001.JCK_STATUS_BASE + _getvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // meke communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + getvalues001.READY); + pipe.println(getvalues001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + getvalues001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(getvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + getvalues001.QUIT + ")"); + log.display("Debugee FAILED"); + return getvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return getvalues001.PASSED; + } + + // tested class with own static fields values + public static class TestedClass { + private static boolean booleanValue = true; + private static final byte byteValue = (byte)0x0F; + protected static char charValue = 'Z'; + protected static final int intValue = 100; + public static short shortValue = (short)10; + public static final long longValue = (long)1000000; + static float floatValue = (float)3.14; + static final double doubleValue = (double)2.8e-12; + static TestedClass objectValue = null; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ReferenceType/Instances/instances001. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Instances + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: instances001 + * debuggee: instances001a + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * For maxInstances in [1, 0, Interger.MAX_VALUE] + * do + * Debugger obtains referenceTypeID for 'nsk.share.jdwp.ReferenceType.instances.instances001.TestClass'. + * Then, debugger creates command packet for Instances command with the + * found referenceTypeID and maxInstances as an arguments, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of instances and instance's ids. + * Debugger checks that received number of instances is correct: + * - if maxInstances=1 only 1 instance should be returned + * - if maxInstances=0 or maxInstances=Integer.MAX_VALUE all instances should be returned + * done + * Also, test performs checks for cases when incorrect data is sent in command. + * Following cases are tested: + * - create command with maxInstances < 0, expect ILLEGAL_ARGUMENT error + * - create command with typeID = -1, expect INVALID_OBJECT error + * - create command with threadID instead of referenceTypeID, expect INVALID_CLASS error + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Instances.instances001.instances001 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Instances.instances001.instances001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ReferenceType.Instances.instances001; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class instances001 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return nsk.jdwp.ReferenceType.Instances.instances001.instances001a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instances001().runIt(argv, out); + } + + private void testClass(long typeID, int maxInstances, int expectedInstances, boolean expectError, int errorCode) { + try { + int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Instances; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("referenceType = " + typeID); + log.display("maxInstances = " + maxInstances); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.addInt(maxInstances); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command, expectError, errorCode); + + if (expectError) + return; + + int instances = reply.getInt(); + log.display("instances = " + instances); + + // check that correct value of 'instances' was received + if (instances != expectedInstances) { + setSuccess(false); + log.complain("Unexpected 'instances' value: " + instances + ", expected is " + expectedInstances); + } + + for (int i = 0; i < instances; i++) { + JDWP.Value value = reply.getValue(); + log.display("tagged-ObjectID = " + value); + } + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + // force GC in debuggee VM to avoid collection of weak references during test execution + forceGC(); + pipe.println(instances001a.COMMAND_CREATE_TEST_INSTANCES); + + if (!isDebuggeeReady()) + return; + + int expectedInstances = instances001a.expectedCount; + + String testClassName = nsk.jdwp.ReferenceType.Instances.instances001.TestClass.class.getName(); + + long typeID = debuggee.getReferenceTypeID(createTypeSignature(testClassName)); + + + // create command with maxInstances=1, only 1 instance should be returned + testClass(typeID, 1, 1, false, 0); + // create command with maxInstances=0, all instances should be returned + testClass(typeID, 0, expectedInstances, false, 0); + // create command with maxInstances=Integer.MAX_VALUE, all instances should be returned + testClass(typeID, Integer.MAX_VALUE, expectedInstances, false, 0); + + // create command with maxInstances < 0, expect ILLEGAL_ARGUMENT error + testClass(typeID, -1, expectedInstances, true, JDWP.Error.ILLEGAL_ARGUMENT); + + // create command with typeID = 1, expect INVALID_OBJECT error + testClass(-1, Integer.MAX_VALUE, expectedInstances, true, JDWP.Error.INVALID_OBJECT); + + // create command with threadID instead of referenceTypeID, expect INVALID_CLASS error + testClass(debuggee.getThreadID("main"), Integer.MAX_VALUE, expectedInstances, true, JDWP.Error.INVALID_CLASS); + + // if GC occurs during test the results should be ignored + resetStatusIfGC(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ReferenceType.Instances.instances001; + +import java.util.ArrayList; +import nsk.share.ReferringObjectSet; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdwp.AbstractJDWPDebuggee; + +class TestClass { + +} + +public class instances001a extends AbstractJDWPDebuggee { + public static final int expectedCount = HeapwalkingDebuggee.includedIntoInstancesCountTypes.size(); + + private ArrayList referrers = new ArrayList(); + + public static final String COMMAND_CREATE_TEST_INSTANCES = "COMMAND_CREATE_TEST_INSTANCES"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_CREATE_TEST_INSTANCES)) { + // create object instances reachable via references with types which should be supported by command ReferenceType.Instances + for (String referenceType : HeapwalkingDebuggee.includedIntoInstancesCountTypes) { + referrers.add(new ReferringObjectSet(new TestClass(), 1, referenceType)); + } + + return true; + } + + return false; + } + + public static void main(String args[]) { + new instances001a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ReferenceType/Instances/instances002. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Instances + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: instances002 + * debuggee: instances002a + * Debuggee contains 5 static fields with names instance1, ..., instance5 initialized with + * different instances of 'nsk.jdwp.ReferenceType.Instances.instances002.TestClass' and + * there are no more instances of 'nsk.jdwp.ReferenceType.Instances.instances002.TestClass' in debugee VM. + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Debugger obtains referenceTypeID for 'nsk.jdwp.ReferenceType.Instances.instances002.TestClass'. + * Then, debugger creates command packet for Instances command with the + * found referenceTypeID and maxInstances as an arguments, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of instances and instance's ids. + * Debugger checks that received number of instances is correct. + * Debugger obtains objectIDs for object instances stored in debuggee's fields instance1, ..., instance5 + * and checks that this values and instances ids received via JDWP command are identical. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Instances.instances002.instances002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Instances.instances002.instances002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ReferenceType.Instances.instances002; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; + +public class instances002 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return nsk.jdwp.ReferenceType.Instances.instances002.instances002a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instances002().runIt(argv, out); + } + + private void testClass(String className, int maxInstances, int expectedInstances) { + try { + int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Instances; + + long typeID = debuggee.getReferenceTypeID(className); + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("referenceType = " + typeID); + log.display("maxInstances = " + maxInstances); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.addInt(maxInstances); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command); + + int instances = reply.getInt(); + log.display("instances = " + instances); + + // check that correct value of 'instances' was received + if (instances != expectedInstances) { + setSuccess(false); + log.complain("Unexpected 'instances' value: " + instances + ", expected is " + expectedInstances); + } + + long expectedInstancesID[] = new long[expectedInstances]; + + // initialize expected IDs of instances + for (int i = 0; i < expectedInstances; i++) { + expectedInstancesID[i] = queryObjectID(debuggee.getReferenceTypeID(createTypeSignature(getDebugeeClassName())), "instance" + (i + 1), + JDWP.Tag.OBJECT); + } + + long receivedInstancesID[] = new long[instances]; + + for (int i = 0; i < instances; i++) { + JDWP.Value value = reply.getValue(); + log.display("tagged-ObjectID = " + value); + + receivedInstancesID[i] = ((Long) value.getValue()).longValue(); + } + + // check that correct IDs of instances was received + for (int i = 0; i < instances; i++) { + boolean isIDExpected = false; + + for (int j = 0; j < expectedInstancesID.length; j++) { + if (receivedInstancesID[i] == expectedInstancesID[j]) { + isIDExpected = true; + break; + } + } + + if (!isIDExpected) { + setSuccess(false); + log.complain("Unexpected 'instance' value: " + receivedInstancesID[i]); + } + } + + if (!getSuccess()) { + log.complain("Expected IDs:"); + for (int i = 0; i < expectedInstancesID.length; i++) + log.complain("" + expectedInstancesID[i]); + } + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + int expectedInstances = instances002a.expectedInstanceCount; + + String testClassName = nsk.jdwp.ReferenceType.Instances.instances002.TestClass.class.getName(); + testClass(createTypeSignature(testClassName), 0, expectedInstances); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ReferenceType.Instances.instances002; + +import nsk.share.jdwp.*; + +class TestClass { + +} + +public class instances002a extends AbstractJDWPDebuggee { + public static final int expectedInstanceCount = 5; + + public static TestClass instance1 = new TestClass(); + + public static TestClass instance2 = new TestClass(); + + public static TestClass instance3 = new TestClass(); + + public static TestClass instance4 = new TestClass(); + + public static TestClass instance5 = new TestClass(); + + public static void main(String args[]) { + new instances002a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Interfaces; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class interfaces001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.Interfaces"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "interfaces001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.Interfaces"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Interfaces; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + static final String class_interfaces [][] = { + { DEBUGEE_CLASS_NAME + "$" + "TestedClassInterface1", "" }, + { DEBUGEE_CLASS_NAME + "$" + "TestedClassInterface2", "" } + }; + static final int DECLARED_INTERFACES = class_interfaces.length; + static final long interfaceIDs[] = new long[DECLARED_INTERFACES]; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new interfaces001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + + log.display("Getting ReferenceTypeID for class signature: " + TESTED_CLASS_SIGNATURE); + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + for (int i = 0; i < DECLARED_INTERFACES; i++) { + class_interfaces[i][1] = "L" + class_interfaces[i][0].replace('.', '/') + ";"; + log.display("Getting ReferenceTypeID for interface signature: " + class_interfaces[i][1]); + interfaceIDs[i] = debugee.getReferenceTypeID(class_interfaces[i][1]); + } + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int interfaces = reply.getInt(); + log.display(" interfaces: " + interfaces); + + if (interfaces != DECLARED_INTERFACES) { + log.complain("Unexpected number of declared interfaces in the reply packet:" + interfaces + + " (expected: " + DECLARED_INTERFACES + ")"); + success = false; + } + + for (int i = 0; i < interfaces; i++ ) { + + log.display(" interface #" + i); + + long interfaceID = reply.getReferenceTypeID(); + log.display(" interfaceID: " + interfaceID); + + if (interfaceID != interfaceIDs[i]) { + log.complain("Unexpected interface ID for interface #" + i + " in the reply packet: " + interfaceID + + " (expected: " + interfaceIDs[i] + ")"); + success = false; + } + + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/Interfaces/interfaces001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Interfaces + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test check that + * returned InterfaceIDs are equal to the ReferenceTypeIDs + * queried for these interfaces. + * Test consists of two compoments: + * debugger: interfaces001 + * debuggee: interfaces001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains ReferenceTypeID for tested class, which + * will be used to test JDWP command. Also it obtains ReferenceTypeIDs + * for all interfaces of that class. + * Then, debugger creates command packet for Interfaces command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts interfaces IDs. Also it checks that extracted InterfaceIDs + * are equal to expected ReferenceTypeIDs. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Interfaces.interfaces001 + * nsk.jdwp.ReferenceType.Interfaces.interfaces001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Interfaces.interfaces001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Interfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class interfaces001a { + + public static void main(String args[]) { + interfaces001a _interfaces001a = new interfaces001a(); + System.exit(interfaces001.JCK_STATUS_BASE + _interfaces001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return interfaces001.PASSED; + } + + static public interface TestedClassInterface1 { + public int methodOfInterface1(int x); + } + + static public interface TestedClassInterface2 { + public byte methodOfInterface2(byte b); + } + + static class TestedClass implements TestedClassInterface1, TestedClassInterface2 { +// static class TestedClass implements TestedClassInterface1 { + int foo = 0; + public int methodOfInterface1(int x) { return x; } + public byte methodOfInterface2(byte b) { return b; } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Methods; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class methods001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.Methods"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "methods001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.Methods"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Methods; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + static final String[][] methods = { + {"", "()V"}, + {"byteMethod", "(B)B"}, + {"booleanMethod", "()Z"}, + {"charMethod", "(B)C"}, + {"shortMethod", "(SS)S"}, + {"intMethod", "(IS)I"}, + {"longMethod", "(I)J"}, + {"floatMethod", "(D)F"}, + {"doubleMethod", "()D"}, + {"stringMethod", "(Ljava/lang/String;C)Ljava/lang/String;"}, + {"objectMethod", "()" + TESTED_CLASS_SIGNATURE}, + {"intArrayMethod", "(I)[I"}, + {"", "(Z)V"} + }; + static final int DECLARED_METHODS = methods.length; + static final int METHOD_MODIFIER_FLAGS = JDWP.ModifierFlag.PUBLIC; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new methods001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long declared = reply.getInt(); + log.display(" declared: " + declared); + + if (declared != DECLARED_METHODS) { + log.complain("Unexpected number of declared methods in the reply packet" + declared + + " (expected: " + DECLARED_METHODS + ")"); + success = false; + } + + for (int i = 0; i < declared; i++ ) { + + log.display(" method #" + i); + + long methodID = reply.getMethodID(); + log.display(" methodID: " + methodID); + + String name = reply.getString(); + log.display(" name: " + name); + if (! name.equals(methods[i][0])) { + log.complain("Unexpected name of method #" + i + " in the reply packet: " + name + + " (expected: " + methods[i][0] + ")"); + success = false; + } + + String signature = reply.getString(); + log.display(" signature: " + signature); + if (! signature.equals(methods[i][1])) { + log.complain("Unexpected signature of method #" + i + " in the reply packet: " + signature + + " (expected: " + methods[i][1] + ")"); + success = false; + } + + int modBits = reply.getInt(); + String modBitsString = "0x" + Packet.toHexString(modBits, 8); + log.display(" modBits: " + modBitsString); + modBits &= JDWP.ModifierFlag.METHOD_MASK; + if (modBits != METHOD_MODIFIER_FLAGS) { + String expectedModBitsString = "0x" + Packet.toHexString(METHOD_MODIFIER_FLAGS, 8); + log.complain("Unexpected modifier flags of method #" + i + " in the reply packet: " + modBitsString + + " (expected: " + expectedModBitsString + ")"); + success = false; + } + + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/Methods/methods001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Methods + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * reply contains expected set of fields. + * Test consists of two compoments: + * debugger: methods001 + * debuggee: methods001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class, which + * will be used to test JDWP command. + * Then, debugger creates command packet for Methods command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts fields info. Test checks that all fields are equal to + * expected. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Methods.methods001 + * nsk.jdwp.ReferenceType.Methods.methods001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Methods.methods001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class methods001a { + + public static void main(String args[]) { + methods001a _methods001a = new methods001a(); + System.exit(methods001.JCK_STATUS_BASE + _methods001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return methods001.PASSED; + } + + static class TestedClass { + public TestedClass() {} + public byte byteMethod(byte b) { return b; } + public boolean booleanMethod() { return true; } + public char charMethod(byte b) { return (char) b; } + public short shortMethod(short x, short y) { return (short) (x - y); } + public int intMethod(int x, short y) { return x - y; } + public long longMethod(int x) { return (long) x; } + public float floatMethod(double x) { return (float) x; } + public double doubleMethod() { return 2.48e-10; } + public String stringMethod(String s, char ch) { return s + ch; }; + public TestedClass objectMethod() { return this; } + public int[] intArrayMethod(int n) { return new int[n]; }; + public TestedClass(boolean b) {} + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.MethodsWithGeneric; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * This test checks that the JDWP command MethodsWithGeneric + * from the ReferenceType command set returns generic signature + * information properly.
+ * Debuggee part of the test creates instances of several tested classes with + * methods to be checked. Some of the classes are generic and accordingly + * contain generic methods. Debugger part obtains information for each method + * in a reference type of a tested class. Proper generic signature should be + * returned for the generic methods, or an empty string for non-generic ones. + */ +public class methwithgeneric001 { + static final String DEBUGGEE_CLASS = + "nsk.jdwp.ReferenceType.MethodsWithGeneric.methwithgeneric001t"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.MethodsWithGeneric"; + static final int JDWP_COMMAND_ID = + JDWP.Command.ReferenceType.MethodsWithGeneric; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String[][][] methods = { + {{"", + "()V", + "NULL"}, + {"methwithgeneric001bMeth", + "(Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;)Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;", + "(Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;)Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;"}, + {"methwithgeneric001bMethSt", + "(Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;)Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;", + "(Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;)Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;"}}, + + {{"", + "()V", + "NULL"}, + {"methwithgeneric001cMeth", + "(Ljava/lang/Class;)Ljava/lang/Object;", + "(Ljava/lang/Class;)TU;"}, + {"methwithgeneric001cMethSt", + "(Ljava/lang/Class;)Ljava/lang/Object;", + "(Ljava/lang/Class;)TU;"}}, + + {{"", + "()V", + "NULL"}, + {"methwithgeneric001eMeth", + "(Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001e;)V", + "NULL"}, + {"methwithgeneric001eMethSt", + "(Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001e;)V", + "NULL"}}, + + {{"methwithgeneric001ifMeth", + "()I", + "NULL"}, + {"methwithgeneric001ifMeth2", + "(Ljava/lang/Object;)I", + "(TI;)I"}}, + + {{"", + "()V", + "NULL"}, + {"methwithgeneric001gMeth", + "(Ljava/lang/Byte;Ljava/lang/Double;[Ljava/lang/Class;)V", + "(TA;TB;[Ljava/lang/Class<*>;)V"}, + {"methwithgeneric001gMethSt", + "(Ljava/lang/Byte;Ljava/lang/Double;)V", + "(TA;TB;)V"}} + }; + + static final String[][] classes = { + {"Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001b;", "3"}, + {"Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001c;", "3"}, + {"Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001e;", "3"}, + {"Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001if;", "2"}, + {"Lnsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001g;", "3"} + }; + + static final int CLS_NUM = classes.length; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new methwithgeneric001().runThis(argv, out); + } + + public int runThis(String argv[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + boolean result = true; + + try { + Binder binder = new Binder(argumentHandler, log); + + log.display("Starting debuggee VM ..."); + Debugee debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + + Transport transport = debuggee.getTransport(); + IOPipe pipe = debuggee.createIOPipe(); + + log.display("Waiting for VM_INIT event ..."); + debuggee.waitForVMInit(); + + log.display("Querying for IDSizes ..."); + debuggee.queryForIDSizes(); + + log.display("Resuming debuggee VM ..."); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY + + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd); + + try { + for (int i=0; i>>>>> Create command " + JDWP_COMMAND_NAME + + "\n\twith ReferenceTypeID: " + typeID + + "\n\tof the class: " + classes[i][0]); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("\nWaiting for reply packet ..."); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display(" ... Reply packet received:\n" + reply); + + log.display("\nChecking reply packet header"); + reply.checkHeader(command.getPacketID()); + + /* parsing of reply data: + int declared - Number of declared methods + + ---- Repeated 'declared' times: + methodID methodID - Method ID + string nam - The name of the field + string signature - The JNI signature of the field. + string genericSignature - The generic signature of the field, + or an empty string if there is none. + int modBits - The modifier bit flags (also known as access flags) + ---- + */ + log.display("\nParsing reply packet:"); + reply.resetPosition(); + + long declared = reply.getInt(); + log.display("\tdeclared: " + declared); + int meth_num = Integer.parseInt(classes[i][1]); + if (declared != meth_num) { + log.complain("TEST FAILED: Unexpected number of declared methods in the reply packet:" + + "\n\tGot: " + declared + + "\n\tExpected: " + meth_num + "\n"); + result = false; + } + + for (int j=0; j method #" + j); + + long methodID = reply.getMethodID(); + log.display("\t\tmethodID: " + methodID); + + String name = reply.getString(); + log.display("\t\tname: " + name); + if (!name.equals(methods[i][j][0])) { + log.complain("TEST FAILED: Unexpected name of method #" + i + + " in the reply packet:" + + "\n\tGot: " + name + + "\n\tExpected: " + methods[i][j][0] + "\n"); + result = false; + } + + String signature = reply.getString(); + log.display("\t\tsignature: " + signature); + if (!signature.equals(methods[i][j][1])) { + log.complain("TEST FAILED: Unexpected type signature of field #" + i + + " in the reply packet:" + + "\n\tGot: " + signature + + "\n\tExpected: " + methods[i][j][1] + "\n"); + result = false; + } + + String genSignature = reply.getString(); + log.display("\t\tgeneric signature: " + genSignature); + if (genSignature.length() == 0) // a non-generic field + genSignature = "NULL"; + if (!genSignature.equals(methods[i][j][2])) { + log.complain("TEST FAILED: Unexpected generic signature of field #" + i + + " in the reply packet:" + + "\n\tGot: " + genSignature + + "\n\tExpected: " + methods[i][j][2] + "\n"); + result = false; + } + + int modBits = reply.getInt(); + String modBitsString = "0x" + Packet.toHexString(modBits, 8); + log.display("\t\tmodBits: " + modBitsString); + } + + if (!reply.isParsed()) { + log.complain("TEST FAILED: Extra trailing bytes found in reply packet at: " + + reply.currentPosition()); + result = false; + } else + log.display("\n<<<<<< Reply packet parsed"); + /////// end test of JDWP command + } + + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught exception while testing JDWP command: " + + e); + result = false; + } finally { + log.display("Sending command: " + COMMAND_QUIT + " ..."); + pipe.println(COMMAND_QUIT); + + log.display("Waiting for debuggee exits ..."); + int code = debuggee.waitFor(); + if (code == Consts.JCK_STATUS_BASE + Consts.TEST_PASSED) { + log.display(" ... Debuggee PASSED with the exit code: " + + code); + } else { + log.complain(" ... Debuggee FAILED with the exit code: " + + code); + result = false; + } + } + + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while communicating with debugee: " + + e); + result = false; + } + + if (!result) + return Consts.TEST_FAILED; + + return Consts.TEST_PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * JDWP command set: ReferenceType + * JDWP command: MethodsWithGeneric + * It checks that the command returns generic signature information + * properly. + * Debuggee part of the test creates instances of several tested classes + * with methods to be checked. Some of the classes are generic and + * accordingly contain generic methods. Debugger part obtains information + * for each method in a reference type of a tested class. Proper generic + * signature should be returned for the generic methods, or an empty string + * for non-generic ones. + * COMMENTS + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.MethodsWithGeneric.methwithgeneric001 + * nsk.jdwp.ReferenceType.MethodsWithGeneric.methwithgeneric001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.MethodsWithGeneric.methwithgeneric001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001t.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001t.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.MethodsWithGeneric; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class methwithgeneric001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + // load tested classes + methwithgeneric001b _methwithgeneric001b = + new methwithgeneric001b(); + methwithgeneric001c _methwithgeneric001c = + new methwithgeneric001c(); + methwithgeneric001e _methwithgeneric001e = + new methwithgeneric001e(); + methwithgeneric001if _methwithgeneric001if = + new methwithgeneric001d(); + methwithgeneric001g _methwithgeneric001g = + new methwithgeneric001g(); + + log.display("Debuggee VM started\nSending command: " + + methwithgeneric001.COMMAND_READY); + pipe.println(methwithgeneric001.COMMAND_READY); + + log.display("Waiting for command: " + + methwithgeneric001.COMMAND_QUIT + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd + + "\nDebuggee is exiting ..."); + + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } +} + +/* + * Dummy classes used only for verifying generic signature information + * in a debugger. + */ + +class methwithgeneric001b { + methwithgeneric001b methwithgeneric001bMeth(methwithgeneric001b m) { + return new methwithgeneric001b(); + } + + static methwithgeneric001b methwithgeneric001bMethSt(methwithgeneric001b m) { + return new methwithgeneric001b(); + } +} + +class methwithgeneric001c { + public U methwithgeneric001cMeth(Class klass) throws Exception { + return klass.newInstance(); + } + + static public U methwithgeneric001cMethSt(Class klass) throws Exception { + return klass.newInstance(); + } +} + +interface methwithgeneric001if { + int methwithgeneric001ifMeth(); + + int methwithgeneric001ifMeth2(I v); +} + +class methwithgeneric001d implements methwithgeneric001if { + public int methwithgeneric001ifMeth() { + return 1; + } + + public int methwithgeneric001ifMeth2(T v) { + return 2; + } +} + +class methwithgeneric001e { + void methwithgeneric001eMeth(methwithgeneric001e e) {} + static void methwithgeneric001eMethSt(methwithgeneric001e e) {} +} + +class methwithgeneric001f extends methwithgeneric001e implements methwithgeneric001if { + public int methwithgeneric001ifMeth() { + return 3; + } + + public int methwithgeneric001ifMeth2(Object v) { + return 4; + } +} + +class methwithgeneric001g { + void methwithgeneric001gMeth(A a, B b, Class[] c) {} + + static void methwithgeneric001gMethSt(A a, B b) {} +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Modifiers; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class modifiers001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.Modifiers"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "modifiers001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.Modifiers"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Modifiers; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + static final int TESTED_CLASS_MODIFIER_FLAGS = JDWP.ModifierFlag.PUBLIC + | JDWP.ModifierFlag.FINAL; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new modifiers001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int modBits = reply.getInt(); + String modBitsString = "0x" + Packet.toHexString(modBits, 8); + log.display(" modBits: " + modBitsString); + +// modBits &= JDWP.ModifierFlag.CLASS_MASK; + + if ((JDWP.ModifierFlag.PUBLIC & modBits) == 0) { + log.complain("No expected PUBLIC modifier found into class modifier flags in the reply packet: " + modBitsString + + " (expected: " + Packet.toHexString(JDWP.ModifierFlag.PUBLIC,8) + ")"); + success = false; + } + + if ((JDWP.ModifierFlag.FINAL & modBits) == 0) { + log.complain("No expected FINAL modifier found into class modifier flags in the reply packet: " + modBitsString + + " (expected: " + Packet.toHexString(JDWP.ModifierFlag.FINAL,8) + ")"); + success = false; + } + + if ((JDWP.ModifierFlag.INTERFACE & modBits) != 0) { + log.complain("Unexpected INTERFACE modifier found into class modifier flags in the reply packet: " + modBitsString + + " (not expected: " + Packet.toHexString(JDWP.ModifierFlag.INTERFACE,8) + ")"); + success = false; + } + + if ((JDWP.ModifierFlag.ABSTRACT & modBits) != 0) { + log.complain("Unexpected ABSTRACT modifier found into class modifier flags in the reply packet: " + modBitsString + + " (not expected: " + Packet.toHexString(JDWP.ModifierFlag.ABSTRACT,8) + ")"); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/Modifiers/modifiers001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Modifiers + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * reply contains expected set of class modifiers. + * Test consists of two compoments: + * debugger: modifiers001 + * debuggee: modifiers001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class, which + * will be used to test JDWP command. + * Then, debugger creates command packet for Modifiers command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts fields info. Test checks that the received set of class + * modifiers contains expected flags and does not contain unexpected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Modifiers.modifiers001 + * nsk.jdwp.ReferenceType.Modifiers.modifiers001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Modifiers.modifiers001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Modifiers; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class modifiers001a { + + public static void main(String args[]) { + modifiers001a _modifiers001a = new modifiers001a(); + System.exit(modifiers001.JCK_STATUS_BASE + _modifiers001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return modifiers001.PASSED; + } + + static final public class TestedClass { + int foo = 0; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.NestedTypes; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ReferenceType.NestedTypes. + * + * See nestedtypes001.README for description of test execution. + * + * Test is executed by invoking method runIt(). + * JDWP command is tested in method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class nestedtypes001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.NestedTypes"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "nestedtypes001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ReferenceType.NestedTypes"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.NestedTypes; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // nested classes names and signatures array + static final String nested_classes [][] = { + { TESTED_CLASS_NAME + "$" + "NestedInterface", "" }, + { TESTED_CLASS_NAME + "$" + "StaticNestedClass", "" }, + { TESTED_CLASS_NAME + "$" + "InnerNestedClass", "" } + }; + static final int NESTED_CLASSES = nested_classes.length; + + // nested classes IDs array + static final long nested_classesIDs[] = new long[NESTED_CLASSES]; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new nestedtypes001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debugee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debugee for TypeID of tested class + log.display("Getting ReferenceTypeID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got TypeID: " + typeID); + + // query debugee for TypeIDs of classes been nested + log.display("Getting ReferenceTypeIDs for nested classes"); + queryNestedClassesTypeIDs(); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(typeID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debugee for TypeIDs for nested classes from nested_classes array + * and put them into nested_classesIDs array. + */ + void queryNestedClassesTypeIDs() { + for (int i = 0; i < NESTED_CLASSES; i++) { + nested_classes[i][1] = "L" + nested_classes[i][0].replace('.', '/') + ";"; + log.display("Getting ReferenceTypeID by signature:\n" + + " " + nested_classes[i][1]); + nested_classesIDs[i] = debugee.getReferenceTypeID(nested_classes[i][1]); + log.display(" got TypeID: " + nested_classesIDs[i]); + } + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long typeID) { + + // count nested classes found in the reply packet + int found_classes[] = new int[NESTED_CLASSES]; + for (int i = 0; i < NESTED_CLASSES; i++) { + found_classes[i] = 0; + } + + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + log.display(" ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check number of nested classes + int classes = 0; + try { + classes = reply.getInt(); + log.display(" classes: " + classes); + + if (classes != NESTED_CLASSES) { + log.complain("Unexpected number of nested classes in the reply packet:" + + classes + " (expected: " + NESTED_CLASSES + ")"); + success = false; + } + } catch (BoundException e) { + log.complain("Unable to extract number of nested classes from reply packet:\n\t" + + e.getMessage()); + success = false; + } + + // extract and check TypeID for each nested class + for (int i = 0; i < classes; i++ ) { + log.display(" nested class #" + i); + + // extract TypeTag byte + try { + byte refTypeTag = reply.getByte(); + log.display(" refTypeTag: " + refTypeTag); + } catch (BoundException e) { + log.complain("Unable to extract refTypetag of " + i + " nested class from reply packet:\n\t" + + e.getMessage()); + success = false; + break; + } + + // extract and check TypeID + long referenceTypeID; + try { + referenceTypeID = reply.getReferenceTypeID(); + log.display(" referenceTypeID: " + referenceTypeID); + + } catch (BoundException e) { + log.complain("Unable to extract TypeID of " + i + + " nested class from reply packet:\n\t" + + e.getMessage()); + success = false; + break; + } + + if (referenceTypeID == 0) { + log.complain("Unexpected null ReferenceTypeID for nested class #" + i + + " in the reply packet: " + referenceTypeID); + success = false; + } else { + boolean found = false;; + for (int j = 0; j < NESTED_CLASSES; j++) { + if (referenceTypeID == nested_classesIDs[j]) { + log.display("! Found expected nested class #" + j + ": " + + nested_classes[j][0]); + found = true; + found_classes[j]++; + break; + } + } + if (!found) { + log.complain("Unexpected TypeID of nested class found in reply packet: " + + referenceTypeID); + success = false; + } + } + } + + // check for extra data in reply packet + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.offsetString()); + success = false; + } + + // check if all expected nested classes are found + for (int j = 0; j < NESTED_CLASSES; j++) { + if (found_classes[j] <= 0) { + log.complain("No TypeID for expected nested class found in reply packet: " + + nested_classesIDs[j] + " (" + nested_classes[j][0] + ")"); + success = false; + } else if (found_classes[j] > 1) { + log.complain("Duplicated " + found_classes[j] + " TypeIDs for expected nested class found in reply packet: " + + nested_classesIDs[j] + " (" + nested_classes[j][0] + ")"); + success = false; + } + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: NestedTypes + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned ReferenceTypeIDs for nested types are equal to + * thye expected ones. + * Test consists of two compoments: + * debugger: nestedtypes001 + * debuggee: nestedtypes001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains ReferenceTypeIDs for the tested class + * from debugee, and for all classes been nested for this class. + * Then, debugger creates command packet for NestedTypes command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts ReferenceTypeIDs of the nested types. Also test checks + * that the extreacted ReferenceTypeIDs for nested types are equal + * to the expected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * Test fixed due to test bug: + * 4908513 TEST_BUG: nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001 assumes order + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.NestedTypes.nestedtypes001 + * nsk.jdwp.ReferenceType.NestedTypes.nestedtypes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.NestedTypes.nestedtypes001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.NestedTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class nestedtypes001a { + + public static void main(String args[]) { + nestedtypes001a _nestedtypes001a = new nestedtypes001a(); + System.exit(nestedtypes001.JCK_STATUS_BASE + _nestedtypes001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + nestedtypes001.READY); + pipe.println(nestedtypes001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + nestedtypes001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(nestedtypes001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + nestedtypes001.QUIT + ")"); + log.display("Debugee FAILED"); + return nestedtypes001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return nestedtypes001.PASSED; + } + + // tested class with nested classes + public static class TestedClass { + + public interface NestedInterface { + public int methodFoo(); + } + + public static class StaticNestedClass implements NestedInterface { + int foo = 0; + public int methodFoo() { return foo; } + } + + public class InnerNestedClass extends StaticNestedClass { + public int methodFoo() { return foo + foo; } + } + + public TestedClass() { + // ensure all nested classes are loaded + InnerNestedClass foo = new InnerNestedClass(); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Signature; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class signature001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.Signature"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "signature001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.Signature"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Signature; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new signature001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String signature = reply.getString(); + log.display(" signature: " + signature); + + if (! signature.equals(TESTED_CLASS_SIGNATURE)) { + log.complain("Unexpected class signature found in the reply packet: " + signature + + " (expected: " + TESTED_CLASS_SIGNATURE + ")"); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/Signature/signature001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Signature + * Test checks that debugee accept command and replies + * with correct reply packet. Also test checks that + * returned signature of the requested class is equal + * to the expected one. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test queries debugee VM for ReferenceTypeID for + * debugee class. + * Then test sends Signature command with received ReferenceTypeID + * as an command argument and waits for a reply packet. + * Then test checks if the received reply packet has proper + * structure and extracted signature string is equal to + * the expected signature of debugee class. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Signature.signature001 + * nsk.jdwp.ReferenceType.Signature.signature001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Signature.signature001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class signature001a { + + public static void main(String args[]) { + signature001a _signature001a = new signature001a(); + System.exit(signature001.JCK_STATUS_BASE + _signature001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return signature001.PASSED; + } + + static public class TestedClass { + int foo = 0; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.SignatureWithGeneric; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * This test checks that the JDWP command SignatureWithGeneric + * from the ReferenceType command set returns generic signature + * information properly.
+ * Debuggee part of the test creates instances of several tested classes. Some + * of the classes are generic. Debugger part obtains signature information for + * reference types of the each tested class. Proper generic signature should + * be returned for the generic classes, or an empty string for non-generic ones. + */ +public class sigwithgeneric001 { + static final String DEBUGGEE_CLASS = + "nsk.jdwp.ReferenceType.SignatureWithGeneric.sigwithgeneric001t"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.SignatureWithGeneric"; + static final int JDWP_COMMAND_ID = + JDWP.Command.ReferenceType.SignatureWithGeneric; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String[][] classes = { + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001t;", + "NULL"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001b;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001c;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001d;", + "Ljava/lang/Object;Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001if;"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001e;", + "NULL"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001if;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001f;", + "NULL"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001g;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001h;", + "Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001d;Lnsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001if2;"} + }; + + static final int CLS_NUM = classes.length; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new sigwithgeneric001().runThis(argv, out); + } + + public int runThis(String argv[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + boolean result = true; + + try { + Binder binder = new Binder(argumentHandler, log); + + log.display("Starting debuggee VM ..."); + Debugee debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + + Transport transport = debuggee.getTransport(); + IOPipe pipe = debuggee.createIOPipe(); + + log.display("Waiting for VM_INIT event ..."); + debuggee.waitForVMInit(); + + log.display("Querying for IDSizes ..."); + debuggee.queryForIDSizes(); + + log.display("Resuming debuggee VM ..."); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY + + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd); + + try { + for (int i=0; i>>>>> Create command " + JDWP_COMMAND_NAME + + "\n\twith ReferenceTypeID: " + typeID + + "\n\tof the class: " + classes[i][0]); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("\nWaiting for reply packet ..."); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display(" ... Reply packet received:\n" + reply); + + log.display("\nChecking reply packet header"); + reply.checkHeader(command.getPacketID()); + + /* parsing of reply data: + string signature - The JNI signature for the reference type. + string genericSignature - The generic signature for the reference type + or an empty string if there is none. + */ + log.display("\nParsing reply packet:"); + reply.resetPosition(); + + String signature = reply.getString(); + if (!signature.equals(classes[i][0])) { + log.complain("TEST FAILED: Unexpected signature of tested class #" + + (i+1) + " (" + classes[i][0] + ")" + + " in the reply packet:" + + "\n\tGot: " + signature + + "\n\tExpected: " + classes[i][0] + "\n"); + result = false; + } + else + log.display("\t\tsignature: " + signature); + + String genSignature = reply.getString(); + if (genSignature.length() == 0) // a non-generic class + genSignature = "NULL"; + if (!genSignature.equals(classes[i][1])) { + log.complain("TEST FAILED: Unexpected generic signature of tested class #" + + (i+1) + " (" + classes[i][0] + ")" + + " in the reply packet:" + + "\n\tGot: " + genSignature + + "\n\tExpected: " + classes[i][1] + "\n"); + result = false; + } + else + log.display("\t\tgeneric signature: " + genSignature); + + if (!reply.isParsed()) { + log.complain("TEST FAILED: Extra trailing bytes found in reply packet at: " + + reply.currentPosition()); + result = false; + } else + log.display("\n<<<<<< Reply packet parsed"); + /////// end test of JDWP command + } + + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught exception while testing JDWP command: " + + e); + result = false; + } finally { + log.display("Sending command: " + COMMAND_QUIT + " ..."); + pipe.println(COMMAND_QUIT); + + log.display("Waiting for debuggee exits ..."); + int code = debuggee.waitFor(); + if (code == Consts.JCK_STATUS_BASE + Consts.TEST_PASSED) { + log.display(" ... Debuggee PASSED with the exit code: " + + code); + } else { + log.complain(" ... Debuggee FAILED with the exit code: " + + code); + result = false; + } + } + + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while communicating with debugee: " + + e); + result = false; + } + + if (!result) + return Consts.TEST_FAILED; + + return Consts.TEST_PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * JDWP command set: ReferenceType + * JDWP command: SignatureWithGeneric + * It checks that the command returns generic signature information + * properly. + * Debuggee part of the test creates instances of several tested classes. + * Some of the classes are generic. Debugger part obtains signature + * information for reference types of the each tested class. Proper + * generic signature should be returned for the generic classes, or + * an empty string for non-generic ones. + * COMMENTS + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.SignatureWithGeneric.sigwithgeneric001 + * nsk.jdwp.ReferenceType.SignatureWithGeneric.sigwithgeneric001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.SignatureWithGeneric.sigwithgeneric001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001t.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001t.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.SignatureWithGeneric; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class sigwithgeneric001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + // load tested classes + sigwithgeneric001b _sigwithgeneric001b = + new sigwithgeneric001b(); + sigwithgeneric001c _sigwithgeneric001c = + new sigwithgeneric001c(); + sigwithgeneric001e _sigwithgeneric001e = + new sigwithgeneric001e(); + sigwithgeneric001if _sigwithgeneric001if = + new sigwithgeneric001d(); + sigwithgeneric001f _sigwithgeneric001f = + new sigwithgeneric001f(); + sigwithgeneric001g _sigwithgeneric001g = + new sigwithgeneric001g(); + sigwithgeneric001h _sigwithgeneric001h = + new sigwithgeneric001h(); + + log.display("Debuggee VM started\nSending command: " + + sigwithgeneric001.COMMAND_READY); + pipe.println(sigwithgeneric001.COMMAND_READY); + + log.display("Waiting for command: " + + sigwithgeneric001.COMMAND_QUIT + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd + + "\nDebuggee is exiting ..."); + + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } +} + +/* + * Dummy classes used only for verifying generic signature information + * in a debugger. + */ + +class sigwithgeneric001b {} + +class sigwithgeneric001c {} + +interface sigwithgeneric001if { + int sigwithgeneric001ifMeth(); + + int sigwithgeneric001ifMeth2(I v); +} + +class sigwithgeneric001d implements sigwithgeneric001if { + public int sigwithgeneric001ifMeth() { + return 1; + } + + public int sigwithgeneric001ifMeth2(T v) { + return 2; + } +} + +class sigwithgeneric001e {} + +class sigwithgeneric001f extends sigwithgeneric001e implements sigwithgeneric001if { + public int sigwithgeneric001ifMeth() { + return 3; + } + + public int sigwithgeneric001ifMeth2(Object v) { + return 4; + } +} + +class sigwithgeneric001g {} + +interface sigwithgeneric001if2 {} + +class sigwithgeneric001h + extends sigwithgeneric001d + implements sigwithgeneric001if2 {} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.SourceDebugExtension; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * The test checks that the SourceDebugExtension class file + * attribute can be obtained at the JDWP level of JDPA via + * the SourceDebugExtension command in the + * ReferenceType command set. The command is sent + * by a debugger. Received reply data should contain the debug + * extension string or the JDWP error ABSENT_INFORMATION. + */ +public class srcdebugext001 { + public static final int JCK_STATUS_BASE = 95; + public static final int PASSED = 0; + public static final int FAILED = 2; + static final String DEBUGGEE_CLASS = + "nsk.jdwp.ReferenceType.SourceDebugExtension.srcdebugext001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.SourceDebugExtension"; + static final int JDWP_COMMAND_ID = + JDWP.Command.ReferenceType.SourceDebugExtension; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private Transport transport; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new srcdebugext001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + CommandPacket cmdPack = new CommandPacket(JDWP_COMMAND_ID); + ReplyPacket replyPack = new ReplyPacket(); + + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + try { + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.waitForVMInit(); + pipe = debuggee.createIOPipe(); + debuggee.resume(); + } catch(Exception e) { + log.complain("FAILURE: caught: " + e); + e.printStackTrace(); + return FAILED; + } + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + return quitDebuggee(FAILED); + } + +// send a command packet + transport = debuggee.getTransport(); + long rTypeID = getRefTypeID(DEBUGGEE_CLASS); + cmdPack.addReferenceTypeID(rTypeID); + cmdPack.setLength(); + try { + log.display("Sending a command: " + JDWP_COMMAND_NAME); + transport.write(cmdPack); + log.display("Waiting for reply"); + transport.read(replyPack); + log.display("Reply received:\n" + replyPack); + +// check received reply packet + if (checkReplyPacket(replyPack,cmdPack) != PASSED) + return quitDebuggee(FAILED); + switch(replyPack.getErrorCode()) { + case JDWP.Error.NONE: + replyPack.resetPosition(); + log.display("TEST PASSED: received reply does not contain errors.\n\t" + + "The debug extension string is: " + + replyPack.getString()); + break; + case JDWP.Error.ABSENT_INFORMATION: + log.display("TEST PASSED: received reply contains a valid error: ABSENT_INFORMATION"); + break; + default: + log.complain("Unexpected error code " + + replyPack.getErrorCode() + " in reply:\n" + + replyPack); + return quitDebuggee(FAILED); + } + } catch(Exception e) { + log.complain("FAILURE: caught: " + e); + e.printStackTrace(); + return quitDebuggee(FAILED); + } + return quitDebuggee(PASSED); + } + + private long getRefTypeID(String cls) { + ReplyPacket reply = new ReplyPacket(); + long typeID = 0; + String clsSig = "L" + cls.replace('.', '/') + ";"; + + log.display("\ngetRefTypeID: getting a RefetenceType ID for the signature:\n\t" + + clsSig); + CommandPacket cmd = + new CommandPacket(JDWP.Command.VirtualMachine.ClassesBySignature); + cmd.addString(clsSig); + cmd.setLength(); + try { + log.display("\ngetRefTypeID: sending a command VirtualMachine.ClassesBySignature:\n" + + cmd); + transport.write(cmd); + log.display("getRefTypeID: Waiting for reply"); + transport.read(reply); + log.display("getRefTypeID: Reply received:\n" + reply); + if (checkReplyPacket(reply,cmd) != PASSED) + throw new Failure("TEST FAILED"); +// reply = debuggee.receiveReplyFor(cmd); +// log.display("getRefTypeID: reply received:\n" + reply); + log.display("getRefTypeID: extracting ReferenceTypeID from the reply packet"); + reply.resetPosition(); + +/* parsing of reply data: + int classes - number of reference types that follow + ---- Repeated 'classes' times: + byte refTypeTag - kind of following reference type + referenceTypeID - typeID matching loaded reference type + int status - the current class status + ---- */ + int cls_num = reply.getInt(); + if (cls_num != 1) { + throw new Failure("TEST FAILED: Illegal number of returned classes: " + + cls_num + ", expected: 1"); + } + else + log.display("getRefTypeID: reply data:\n\tnumber of returned classes: " + + cls_num); + byte refTypeTag = reply.getByte(); + typeID = reply.getReferenceTypeID(); + log.display("\treferenceTypeID: " + typeID); + int status = reply.getInt(); + log.display("\tstatus: " + status + "\n"); + } catch(Exception e) { + quitDebuggee(FAILED); + if (e instanceof Failure) + throw new Failure(e); + else { + e.printStackTrace(); + throw new Failure("TEST FAILED: " + e.toString()); + } + } + + if (!reply.isParsed()) { + quitDebuggee(FAILED); + throw new Failure("TEST FAILED: Extra bytes in reply packet at: " + + reply.currentPosition()); + } + + return typeID; + } + + private int checkReplyPacket(ReplyPacket reply, CommandPacket cmd) { + int ret = PASSED; + + if (reply.getFlags() != JDWP.Flag.REPLY_PACKET) { + log.complain("TEST FAILED: Unexpected flags in reply packet:\n\tgot=0x" + + Packet.toHexString(reply.getFlags(), 2) + + " should be: 0x" + + Integer.toHexString(JDWP.Flag.REPLY_PACKET)); + ret = FAILED; + } + if (reply.getPacketID() != cmd.getPacketID()) { + log.complain("TEST FAILED: Unexpected id field in reply packet:\n\tgot=0x" + + Packet.toHexString(reply.getPacketID(), 8) + + " should be: 0x" + Packet.toHexString(cmd.getPacketID(), 8)); + ret = FAILED; + } + return ret; + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the SourceDebugExtension class file + * attribute can be obtained at the JDWP level of JPDA via + * the SourceDebugExtension command in the ReferenceType command + * set. The command is sent by a debugger. Received reply data + * should contain the debug extension string or the JDWP error + * ABSENT_INFORMATION. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.SourceDebugExtension.srcdebugext001 + * nsk.jdwp.ReferenceType.SourceDebugExtension.srcdebugext001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.SourceDebugExtension.srcdebugext001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001t.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001t.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.SourceDebugExtension; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * This is a debuggee class. + */ +public class srcdebugext001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Log log = new Log(System.out, argHandler); + + pipe.println(srcdebugext001.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(srcdebugext001.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(srcdebugext001.JCK_STATUS_BASE + + srcdebugext001.FAILED); + } + log.display("Received command: " + cmd + + "\nDebuggee is exiting..."); + System.exit(srcdebugext001.JCK_STATUS_BASE + + srcdebugext001.PASSED); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.SourceFile; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class srcfile001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.SourceFile"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "srcfile001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.SourceFile"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.SourceFile; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final String TESTED_CLASS_SRCFILENAME = "srcfile001a.java"; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new srcfile001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String sourceFile = reply.getString(); + log.display(" sourceFile: " + sourceFile); + + if (! sourceFile.equals(TESTED_CLASS_SRCFILENAME)) { + log.complain("Unexpected class source file name found in the reply packet: " + sourceFile + + " (expected: " + TESTED_CLASS_SRCFILENAME + ")"); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/SourceFile/srcfile001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: SourceFile + * Test checks that debugee accept command and replies + * with correct reply packet. Also test checks that + * returned source file name for the requested class + * is equal to the expected one. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test queries debugee VM for ReferenceTypeID for + * debugee class. + * Then test sends SourceFile command with received ReferenceTypeID + * as an command argument and waits for a reply packet. + * Then test checks if the received reply packet has proper + * structure and extracted source file name is equal to + * the expected name of the file with debugee class. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee VM exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.SourceFile.srcfile001 + * nsk.jdwp.ReferenceType.SourceFile.srcfile001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.SourceFile.srcfile001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.SourceFile; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class srcfile001a { + + public static void main(String args[]) { + srcfile001a _srcfile001a = new srcfile001a(); + System.exit(srcfile001.JCK_STATUS_BASE + _srcfile001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return srcfile001.PASSED; + } + + static public class TestedClass { + int foo = 0; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Status; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class status001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ReferenceType.Status"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "status001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ReferenceType.Status"; + static final int JDWP_COMMAND_ID = JDWP.Command.ReferenceType.Status; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + static final int TESTED_CLASS_STATUS = JDWP.ClassStatus.VERIFIED + | JDWP.ClassStatus.PREPARED + | JDWP.ClassStatus.INITIALIZED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new status001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + long typeID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + + // begin test of JDWP command + + log.display("Create command " + JDWP_COMMAND_NAME + + " with ReferenceTypeID: " + typeID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addReferenceTypeID(typeID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int status = reply.getInt(); + String statusString = "0x" + Packet.toHexString(status, 4); + log.display(" status: " + statusString); + + if (status != TESTED_CLASS_STATUS) { + log.complain("Unexpected class status extracted from reply packet: " + statusString + + " (expected: " + "0x" + Packet.toHexString(TESTED_CLASS_STATUS, 4) + ")"); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + } catch (Exception e) { + + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + + } finally { + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while connecting to debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ReferenceType/Status/status001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ReferenceType + * command: Status + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: status001 + * debuggee: status001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Next, debugger obtains referenceTypeID for debuggee class, which + * will be used to test JDWP command. + * Then, debugger creates command packet for Status command with the + * found referenceTypeID as an argument, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts classObjectID. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ReferenceType.Status.status001 + * nsk.jdwp.ReferenceType.Status.status001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ReferenceType.Status.status001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ReferenceType.Status; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class status001a { + + public static void main(String args[]) { + status001a _status001a = new status001a(); + System.exit(status001.JCK_STATUS_BASE + _status001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return status001.PASSED; + } + + static public class TestedClass { + int foo = 0; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.GetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: StackFrame.GetValues. + * + * See getvalues001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class getvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.StackFrame.GetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "getvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "StackFrame.GetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.StackFrame.GetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + getvalues001a.OBJECT_CLASS_NAME; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // names of the static fields with the tested thread and object values + static final String TESTED_THREAD_FIELD_NAME = getvalues001a.THREAD_FIELD_NAME; + static final String TESTED_OBJECT_FIELD_NAME = getvalues001a.OBJECT_FIELD_NAME; + static final String TESTED_OBJECT_METHOD_NAME = getvalues001a.OBJECT_METHOD_NAME; + + // list of tested variables names and values + static final Object variables[][] = { + { "booleanValue", "boolean", new Boolean(true), new Byte(JDWP.Tag.BOOLEAN)}, + { "byteValue", "byte", new Byte((byte)0x0F), new Byte(JDWP.Tag.BYTE) }, + { "charValue", "char", new Character('Z'), new Byte(JDWP.Tag.CHAR) }, + { "intValue", "int", new Integer(100), new Byte(JDWP.Tag.INT) }, + { "shortValue", "short", new Short((short)10), new Byte(JDWP.Tag.SHORT) }, + { "longValue", "long", new Long((long)1000000), new Byte(JDWP.Tag.LONG) }, + { "floatValue", "float", new Float((float)3.14), new Byte(JDWP.Tag.FLOAT) }, + { "doubleValue", "double", new Double((double)2.8e-12), new Byte(JDWP.Tag.DOUBLE) }, + { "objectValue", "objectID", new Long((long)0), new Byte(JDWP.Tag.OBJECT) } + }; + static final int VARIABLES_COUNT = variables.length; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new getvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting tested classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for tested methodID + log.display("Getting tested methodID by name: " + TESTED_OBJECT_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_OBJECT_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // query debugee for indexes of the method local variables + log.display("Getting indexes of the tested local variables for methodID: " + methodID); + int indexes[] = queryVariableIndexes(classID, methodID); + log.display(" got indexes: " + indexes.length); + + // query debuggee for tested objectID value from static field + log.display("Getting tested objectID value from static field: " + + TESTED_OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, TESTED_OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // query debuggee for tested threadID value from static field + log.display("Getting tested threadID value from static field: " + + TESTED_THREAD_FIELD_NAME); + threadID = queryObjectID(classID, TESTED_THREAD_FIELD_NAME, JDWP.Tag.THREAD); + log.display(" got threadID: " + threadID); + + // suspend tested thread into debuggee + log.display("Suspending thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + log.display(" thread suspended"); + + // query debuggee for current frameID of the tested thread + log.display("Getting current frameID for the threadID: " + + threadID); + long frameID = debugee.getCurrentFrameID(threadID); + log.display(" got frameID: " + frameID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(frameID, threadID, indexes); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static field of the class. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has expected tag + if (value.getTag() != tag) { + throw new Failure("Unexpected tag for object value returned: " + + value.getTag() + " (expected: " + tag + ")"); + } + + // extract objectID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Query debugee for indexes of the local method variables. + */ + int[] queryVariableIndexes(long classID, long methodID) { + // create array for expected indexes + int indexes[] = new int[VARIABLES_COUNT]; + for (int i = 0; i < VARIABLES_COUNT; i++) { + indexes[i] = 0; + } + + // obtain variable indexes from debuggee + int count = 0; + try { + CommandPacket command = new CommandPacket(JDWP.Command.Method.VariableTable); + command.addReferenceTypeID(classID); + command.addMethodID(methodID); + command.setLength(); + + ReplyPacket reply = debugee.receiveReplyFor(command); + reply.resetPosition(); + + int argCount = reply.getInt(); + long slots = reply.getInt(); + if (slots < VARIABLES_COUNT) { + throw new Failure("Too few method local variables returned: " + slots + + " (expected: at least " + VARIABLES_COUNT + ")"); + } + + for (int i = 0; i < slots; i++ ) { + long codeindex = reply.getLong(); + String name = reply.getString(); + String signature = reply.getString(); + int length = reply.getInt(); + int slot = reply.getInt(); + + for (int j = 0; j < VARIABLES_COUNT; j++) { + if (variables[j][0].equals(name)) { + indexes[j] = slot; + break; + } + } + } + + } catch (BoundException e) { + log.complain("Unable to extract local variable indexes from the reply packet:\n\t" + + e.getMessage()); + throw new Failure("Error occured while getting local variable indexes for methodID:" + + methodID); + } + + return indexes; + } + + /** + * Check i-th value from the reply packet. + */ + void checkValue(int i, JDWP.Value value) { + if (!variables[i][2].equals(value.getValue())) { + log.complain("Unexpected value for " + i + " variable (" + + variables[i][0] + ") received: " + value + + " (expected: " + variables[i][2] + ")"); + success = false; + } + } + + /** + * Perform testing JDWP command for specified frameID. + */ + void testCommand(long frameID, long threadID, int indexes[]) { + int slots = indexes.length; + + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" frameID: " + frameID); + command.addFrameID(frameID); + log.display(" slots: " + slots); + command.addInt(slots); + + // add code indexes of the requested variables + for (int i = 0; i < slots; i++) { + log.display(" slot #" + i + ":"); + log.display(" slot: " + indexes[i]); + command.addInt(indexes[i]); + byte tag = ((Byte)variables[i][3]).byteValue(); + log.display(" sigbyte: " + tag); + command.addByte(tag); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract and check number of values + int values = 0; + try { + values = reply.getInt(); + log.display(" values: " + values); + + } catch (BoundException e) { + log.complain("Unable to extract number of values form reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check if number of values are as expected + if (values < 0) { + log.complain("Negative number of values received:" + values + + " (expected: " + slots + ")"); + success = false; + } else if (values != slots) { + log.complain("Unexpected number of values received:" + values + + " (expected: " + slots + ")"); + success = false; + } + + // extract and check each value + for (int i = 0; i < values; i++ ) { + log.display(" value #" + i + " (variable: " + variables[i][0] + ")"); + + // extract value + JDWP.Value value = null; + try { + value = reply.getValue(); + log.display(" slotValue: " + value); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " slot value:\n\t" + + e.getMessage()); + success = false; + break; + } + + // extract and check value by known type tag + checkValue(i, value); + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/StackFrame/GetValues/getvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: StackFrame + * command: GetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned values for requested local variables is the same + * as expected. + * Test consists of two compoments: + * debugger: getvalues001 + * debuggee: getvalues001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested class + * and object ID and threadID as values of the class static fields. + * Also debugger suspends the thread and gets frameID for the + * current thread frameID and indexes of its local variables. + * Thread is suspended on the invokation of method for the tested object. + * Then, debugger creates command packet for StackFrame.GetValues + * command with the found threadID, frameID and indexes of local variables + * as arguments, writes packet to the transport channel, and waits + * for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts variables values. Also test checks that returned values + * are equals to the expected ones. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.StackFrame.GetValues.getvalues001 + * nsk.jdwp.StackFrame.GetValues.getvalues001a + * @comment debuggee should be compiled w/ debug info + * @clean nsk.jdwp.StackFrame.GetValues.getvalues001a + * @compile -g:lines,source,vars ../getvalues001a.java + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.StackFrame.GetValues.getvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.GetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class getvalues001a { + + // name of the tested object and thread classes + public static final String OBJECT_CLASS_NAME = "TestedObjectClass"; + public static final String THREAD_CLASS_NAME = "TestedThreadClass"; + public static final String THREAD_NAME = "TestedThreadName"; + + // name of the static fields with the tested object values + public static final String THREAD_FIELD_NAME = "thread"; + public static final String OBJECT_FIELD_NAME = "object"; + public static final String OBJECT_METHOD_NAME = "testedMethod"; + + // notification object to notify debuggee that thread is ready + private static Object threadReady = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + getvalues001a _getvalues001a = new getvalues001a(); + System.exit(getvalues001.JCK_STATUS_BASE + _getvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread and object + log.display("Creating object of tested class"); + TestedObjectClass.object = new TestedObjectClass(); + log.display("Creating tested thread"); + TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadReady) { + TestedObjectClass.thread.start(); + try { + threadReady.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + getvalues001.READY); + pipe.println(getvalues001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(getvalues001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + getvalues001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(getvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + getvalues001.QUIT + ")"); + log.complain("Debugee FAILED"); + return getvalues001.FAILED; + } + + // allow started thread to finish + } + + // wait for tested thread finished + try { + log.display("Waiting for tested thread finished"); + TestedObjectClass.thread.join(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished:\n\t" + + e); + log.complain("Debugee FAILED"); + return getvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return getvalues001.PASSED; + } + + // tested thread class + public static class TestedThreadClass extends Thread { + + TestedThreadClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // invoke tested method for the tested object from the tested thread + TestedObjectClass.object.testedMethod(); + + log.display("Tested thread finished"); + } + + } + + // tested object class + public static class TestedObjectClass { + + // field with the tested thread and object values + public static volatile TestedThreadClass thread = null; + public static volatile TestedObjectClass object = null; + + public void testedMethod() { + // local variables + boolean booleanValue = true; + byte byteValue = (byte)0x0F; + char charValue = 'Z'; + int intValue = 100; + short shortValue = (short)10; + long longValue = (long)1000000; + float floatValue = (float)3.14; + double doubleValue = (double)2.8e-12; + Object objectValue = null; + + log.display("Tested frame entered"); + + // notify debuggee that tested thread ready for testing + synchronized (threadReady) { + threadReady.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested frame dropped"); + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.PopFrames; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: StackFrame.PopFrames. + * + * See popframes001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class popframes001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_POP_FRAMES; + static final String VM_CAPABILITY_NAME = "canPopFrames"; + + // package and classes names + static final String PACKAGE_NAME = "nsk.jdwp.StackFrame.PopFrames"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "popframes001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command + static final String JDWP_COMMAND_NAME = "StackFrame.PopFrames"; + static final int JDWP_COMMAND_ID = JDWP.Command.StackFrame.PopFrames; + + // tested class name and signature + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedThreadClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // field and method names + static final String TESTED_METHOD_NAME = "testedMethod"; + static final int BREAKPOINT_LINE_NUMBER = popframes001a.BREAKPOINT_LINE_NUMBER; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // data obtained from debuggee + long testedClassID = 0; + long testedThreadID = 0; + long testedMethodID = 0; + long testedFrameID = 0; + int breakpointRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new popframes001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); // minutes + timeout = waitTime * 60 * 1000; // milliseconds + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee VM"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debuggee launched"); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for VM_INIT event + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // check for VM capability + log.display("\n>>> Checking VM capability \n"); + log.display("Getting new VM capability: " + VM_CAPABILITY_NAME); + boolean capable = debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME); + log.display(" ... got VM capability: " + capable); + + // exit as PASSED if this capability is not supported + if (!capable) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // prepare debuggee for testing and obtain required data + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>> Testing JDWP command \n"); + testCommand(); + + // check command results + if (success) { + log.display("\n>>> Checking result of tested command \n"); + checkResult(); + } + + // finish debuggee + log.display("\n>> Finishing debuggee \n"); + + // clear BREAKPOIN event request + log.display("Clearing BREAKPOINT event requestID: " + breakpointRequestID); + debugee.clearEventRequest(JDWP.EventKind.BREAKPOINT, breakpointRequestID); + log.display(" ... request cleared"); + + // resume debuggee after testing command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for VM_DEATH event + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + log.display(" ... VM_DEATH event received"); + dead = true; + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + log.display("\n>>> Finishing test \n"); + + // disconnect debugee and wait for its exit + if (debugee != null) { + quitDebugee(); + } + } + + // check result + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + out.println("TEST PASSED"); + return PASSED; + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for tested class loaded on debuggee startup and obtain its classID + log.display("Waiting for class loaded:\n\t" + TESTED_CLASS_NAME); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, + JDWP.SuspendPolicy.ALL); + log.display(" ... class loaded with classID: " + testedClassID); + + // query debuggee for tested methodID + log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + log.display(""); + + // make BREAKPOINT event request + log.display("Creating breakpoint requests at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE_NUMBER); + breakpointRequestID = + debugee.requestBreakpointEvent(JDWP.TypeTag.CLASS, + testedClassID, testedMethodID, + BREAKPOINT_LINE_NUMBER, + JDWP.SuspendPolicy.ALL); + log.display(" ... got breakpoint requestID: " + breakpointRequestID); + + // resume debuggee after testing command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + log.display(""); + + // wait for BREAKPOINT event + log.display("Waiting for BREAKPOINT event for requestID: " + breakpointRequestID); + testedThreadID = waitForBreakpointEvent(breakpointRequestID, "first"); + log.display(" ... breakpoint reached with threadID: " + testedThreadID); + + // query debuggee for top frameID + log.display("Getting top frameID for threadID: " + testedThreadID); + testedFrameID = queryTopFrameID(testedThreadID); + log.display(" ... got frameID: " + testedFrameID); + log.display(""); + + // tested thread is suspended by an event + log.display("Tested thread is suspended by BREAKPOINT event before pop frameID: " + + testedFrameID); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + testedThreadID); + command.addObjectID(testedThreadID); + log.display(" frameID: " + testedFrameID); + command.addFrameID(testedFrameID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet for tested command:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no reply data to parse + log.display(" no reply data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... packed data parsed"); + } + + /** + * Check result of the tested JDWP command. + */ + void checkResult() { + // resume debuggee after sending command + log.display("Resuming debuggee after command"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for BREAKPOINT event + log.display("Waiting for second BREAKPOINT event for requestID: " + breakpointRequestID); + long threadID = waitForBreakpointEvent(breakpointRequestID, "second"); + log.display(" ... breakpoint secondly reached with threadID: " + threadID); + + log.display("Tested method was invoked two times as expected"); + } + + /** + * Query debuggee for top frameID value for given threadID. + */ + long queryTopFrameID(long threadID) { + String error = "Error occured while getting top frameID for threadID: " + threadID; + + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Frames); + command.addObjectID(threadID); + command.addInt(0); // top frame index + command.addInt(1); // number of frames + + ReplyPacket reply = debugee.receiveReplyFor(command, "ThreadReference.Frames"); + reply.resetPosition(); + + try { + int frames = reply.getInt(); + if (frames != 1) { + log.complain("Wrong number of frames returned in reply packet: " + frames + + " (expected: " + 1 + ")"); + throw new Failure(error); + } + long frameID = reply.getFrameID(); + return frameID; + } catch (BoundException e) { + log.complain("Unable to extract data from reply packet:\n\t" + + e.getMessage()); + throw new Failure(error); + } + } + + /** + * Wait for BREAKPOINT event made by the given request and return threadID. + * Debuggee will be left suspended by the BREAKPOINT event. + */ + public long waitForBreakpointEvent(int requestID, String kind) { + String error = "Error occured while waiting for " + kind + " BREAKPOINT event"; + + for(;;) { + EventPacket event = debugee.receiveEvent(); + byte eventSuspendPolicy = 0; + long eventThreadID = 0; + try { + eventSuspendPolicy = event.getByte(); + int events = event.getInt(); + for (int i = 0; i < events; i++) { + // check event kind + byte eventKind = event.getByte(); + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.complain("Unexpected VM_DEATH event received: " + eventKind + + " (expected: " + JDWP.EventKind.BREAKPOINT +")"); + dead = true; + throw new Failure(error); + } else if (eventKind != JDWP.EventKind.BREAKPOINT) { + log.complain("Unexpected event kind received: " + eventKind + + " (expected: " + JDWP.EventKind.BREAKPOINT +")"); + throw new Failure(error); + } + + // extract specific BREAKPOINT event data + int eventRequestID = event.getInt(); + eventThreadID = event.getObjectID(); + JDWP.Location eventLocation = event.getLocation(); + + if (eventRequestID == requestID) { + return eventThreadID; + } else { + log.complain("Unexpected BREAKPOINT event received with requestID: " + + eventRequestID + " (expected: " + requestID + ")"); + } + } + } catch (BoundException e) { + log.complain("Unable to extract data from event packet while waiting for BREAKPOINT event:\n\t" + + e.getMessage() + "\n" + event); + throw new Failure(error); + } + + // resume debuggee after unhandled event set + debugee.resumeEvent(eventSuspendPolicy, eventThreadID); + } + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/StackFrame/PopFrames/popframes001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: StackFrame + * command: PopFrames + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * after current frame is popped the tested method is invoked + * second time. + * Test consists of two compoments: + * debugger: popframes001 + * debuggee: popframes001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded, requests methodID + * for tested method, sets breakpoint and wait for breakpoint reached. + * After breakpoint event is received with a thread, debugger gets top + * stack frame for this thread. + * Then, debugger creates command packet for StackFrame.PopFrames + * command with the found threadID and frameID, writes this packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks if no reply data returned in the packet. + * Then, checks if the tested method will be invoked second time. + * To do so, it resumes debuggee and waits for BREAKPOINT event + * will be received again. If expected BREAKPOINT event is not received, + * debugger complains an error. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.StackFrame.PopFrames.popframes001 + * nsk.jdwp.StackFrame.PopFrames.popframes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.StackFrame.PopFrames.popframes001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.StackFrame.PopFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class popframes001a { + + // name of the tested thread + public static final String THREAD_NAME = "testedThread"; + + // line nunber for breakpoint + public static final int BREAKPOINT_LINE_NUMBER = 113; + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + popframes001a _popframes001a = new popframes001a(); + System.exit(popframes001.JCK_STATUS_BASE + _popframes001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating testing thread"); + TestedThreadClass thread = new TestedThreadClass(THREAD_NAME); + log.display(" ... thread created"); + + // start tested thread + log.display("Starting tested thread"); + thread.start(); + log.display(" ... thread started"); + + // wait for tested thread finished + try { + log.display("Waiting for tested thread finished"); + thread.join(); + log.display(" ... thread finished"); + } catch(InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished:\n\t" + e); + log.display("Debugee FAILED"); + return popframes001.FAILED; + } + + log.display("Debugee PASSED"); + return popframes001.PASSED; + } + + // tested thread class + public static class TestedThreadClass extends Thread { + + // number of invokations of tested method + public static volatile int invokations = 0; + + public TestedThreadClass(String name) { + super(name); + } + + // invoke tested method + public void run() { + log.display("Tested thread: started"); + + // invoke tested method + int foo = 100; + foo = testedMethod(foo); + + log.display("Tested thread: finished"); + } + + // tested method to pop frames + public int testedMethod(int arg) { + invokations++; + log.display("Tested method invoked " + invokations + " time"); + int boo = 0; + + log.display("Breakpoint line reached"); + // next line is for breakpoint + boo = arg * 2; // BREAKPOINT_LINE_NUMBER + log.display("Breakpoint line passed"); + + return boo; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,599 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.SetValues; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: StackFrame.SetValues. + * + * See setvalues001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class setvalues001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String RUN = "run"; + static final String DONE = "done"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.StackFrame.SetValues"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "setvalues001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "StackFrame.SetValues"; + static final int JDWP_COMMAND_ID = JDWP.Command.StackFrame.SetValues; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + setvalues001a.OBJECT_CLASS_NAME; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // target values class name and signature constants + static final String TARGET_VALUES_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TargetValuesClass"; + static final String TARGET_VALUES_CLASS_SIGNATURE = "L" + TARGET_VALUES_CLASS_NAME.replace('.', '/') + ";"; + + // names of the static fields with the tested thread and object values + static final String TESTED_THREAD_FIELD_NAME = setvalues001a.THREAD_FIELD_NAME; + static final String TESTED_OBJECT_FIELD_NAME = setvalues001a.OBJECT_FIELD_NAME; + static final String TESTED_OBJECT_METHOD_NAME = setvalues001a.OBJECT_METHOD_NAME; + + // list of tested variables names and values + static final Object variables[] = { + "booleanValue", + "byteValue", + "charValue", + "intValue", + "shortValue", + "longValue", + "floatValue", + "doubleValue", + "stringValue", + "objectValue" + }; + static final int VARIABLES_COUNT = variables.length; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new setvalues001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // get target values from static fields + + // query debugee for classID for the class with target values + log.display("Getting classID for class with target values by signature:\n" + + " " + TARGET_VALUES_CLASS_SIGNATURE); + long targetValuesClassID = + debugee.getReferenceTypeID(TARGET_VALUES_CLASS_SIGNATURE); + log.display(" got classID: " + targetValuesClassID); + + // query debugee for fieldIDs of the class static fields + log.display("Getting fieldIDs for static fields of the class"); + long fieldIDs[] = queryClassFieldIDs(targetValuesClassID); + log.display(" got fields: " + fieldIDs.length); + + // query debugee for values of the fields + log.display("Getting values of the static fields"); + JDWP.Value values[] = + queryClassFieldValues(targetValuesClassID, fieldIDs); + log.display(" got values: " + values.length); + + // get indexes of local variables + + // query debugee for classID of the tested class + log.display("Getting tested classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long testedClassID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + testedClassID); + + // query debuggee for tested methodID + log.display("Getting tested methodID by name: " + TESTED_OBJECT_METHOD_NAME); + long methodID = debugee.getMethodID(testedClassID, TESTED_OBJECT_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // query debugee for indexes of the method local variables + log.display("Getting indexes of the tested local variables for methodID: " + methodID); + int indexes[] = queryVariableIndexes(testedClassID, methodID); + log.display(" got indexes: " + indexes.length); + + // get tested objectID and threadID from static fields + + // query debuggee for tested objectID value from static field + log.display("Getting tested objectID value from static field: " + + TESTED_OBJECT_FIELD_NAME); + long objectID = queryObjectID(testedClassID, TESTED_OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // query debuggee for tested threadID value from static field + log.display("Getting tested threadID value from static field: " + + TESTED_THREAD_FIELD_NAME); + threadID = queryObjectID(testedClassID, TESTED_THREAD_FIELD_NAME, JDWP.Tag.THREAD); + log.display(" got threadID: " + threadID); + + // suspend tested thread into debuggee + log.display("Suspending thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + log.display(" thread suspended"); + + // get current frameID and test JDWP command + + // query debuggee for current frameID of the tested thread + log.display("Getting current frameID for the threadID: " + + threadID); + long frameID = debugee.getCurrentFrameID(threadID); + log.display(" got frameID: " + frameID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(frameID, threadID, indexes, values); + + // check confirmation from debuggee that values have been set correctly + log.display("\n>>> Checking that the values have been set correctly \n"); + + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + + checkValuesChanged(); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Finally resuming potentially suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static field of the class. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has expected tag + if (value.getTag() != tag) { + throw new Failure("Unexpected tag for object value returned: " + + value.getTag() + " (expected: " + tag + ")"); + } + + // extract objectID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Query debugee for indexes of the local method variables. + */ + int[] queryVariableIndexes(long classID, long methodID) { + // create array for expected indexes + int indexes[] = new int[VARIABLES_COUNT]; + for (int i = 0; i < VARIABLES_COUNT; i++) { + indexes[i] = 0; + } + + // obtain variable indexes from debuggee + int count = 0; + try { + CommandPacket command = new CommandPacket(JDWP.Command.Method.VariableTable); + command.addReferenceTypeID(classID); + command.addMethodID(methodID); + command.setLength(); + + ReplyPacket reply = debugee.receiveReplyFor(command); + reply.resetPosition(); + + int argCount = reply.getInt(); + long slots = reply.getInt(); + + for (int i = 0; i < slots; i++ ) { + long codeindex = reply.getLong(); + String name = reply.getString(); + String signature = reply.getString(); + int length = reply.getInt(); + int slot = reply.getInt(); + + for (int j = 0; j < VARIABLES_COUNT; j++) { + if (variables[j].equals(name)) { + indexes[j] = slot; + break; + } + } + } + + } catch (BoundException e) { + log.complain("Unable to extract local variable indexes from the reply packet:\n\t" + + e.getMessage()); + throw new Failure("Error occured while getting local variable indexes for methodID:" + + methodID); + } + + // check that all expected fieldIDs received + int notfound = 0; + for (int i = 0; i < VARIABLES_COUNT; i++) { + if(indexes[i] == 0) { + log.complain("Not found index for local variable: " + variables[i]); + notfound++; + } + } + if (notfound > 0) { + throw new Failure("Unable to get indexes for " + notfound + + " local variables for methodID: " + methodID); + } + return indexes; + } + + /** + * Query debugee for fieldID's of the class static fields. + */ + long[] queryClassFieldIDs(long classID) { + + // create array of fieldID's corresponding to tested variables + long[] fieldIDs = new long[VARIABLES_COUNT]; + for (int i = 0; i < VARIABLES_COUNT; i++) { + fieldIDs[i] = 0; + } + + // compose ReferenceType.Fields command packet + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(classID); + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract fieldIDs from the reply packet + try { + reply.resetPosition(); + + int declared = reply.getInt(); + + for (int i = 0; i < declared; i++ ) { + long fieldID = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + // find variable with the same name + for (int j = 0; j < VARIABLES_COUNT; j++) { + if (variables[j].equals(name)) { + fieldIDs[j] = fieldID; + } + } + } + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.Fields command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fieldIDs for classID: " + classID); + } + + // check that all expected fieldIDs received + int notfound = 0; + for (int i = 0; i < VARIABLES_COUNT; i++) { + if(fieldIDs[i] == 0) { + log.complain("Not found fieldID for static field: " + variables[i]); + notfound++; + } + } + if (notfound > 0) { + throw new Failure("Unable to get fiedIDs for " + notfound + + " static fields for classID: " + classID); + } + return fieldIDs; + } + + /** + * Query debugee for values of the class fields. + */ + JDWP.Value[] queryClassFieldValues(long classID, long fieldIDs[]) { + // compose ReferenceType.Fields command packet + int count = fieldIDs.length; + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.GetValues); + command.addReferenceTypeID(classID); + command.addInt(count); + for (int i = 0; i < count; i++) { + command.addFieldID(fieldIDs[i]); + } + command.setLength(); + + // send the command and receive reply + ReplyPacket reply = debugee.receiveReplyFor(command); + + // extract values from the reply packet + try { + reply.resetPosition(); + + int valuesCount = reply.getInt(); + if (valuesCount != count) { + throw new Failure("Unexpected number of values of static fields returned: " + + valuesCount + " (expected: " + count + ")"); + } + + JDWP.Value values[] = new JDWP.Value[valuesCount]; + for (int i = 0; i < valuesCount; i++ ) { + JDWP.Value value = reply.getValue(); + values[i] = value; + } + return values; + } catch (BoundException e) { + log.complain("Unable to parse reply packet for ReferenceType.SetValues command:\n\t" + + e); + log.complain("Received reply packet:\n" + + reply); + throw new Failure("Error occured while getting static fields values for classID: " + classID); + } + } + + /** + * Perform testing JDWP command for specified frameID. + */ + void testCommand(long frameID, long threadID, int indexes[], JDWP.Value values[]) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" frameID: " + frameID); + command.addFrameID(frameID); + log.display(" slotValues: " + VARIABLES_COUNT); + command.addInt(VARIABLES_COUNT); + + // add indexes and new values of the tested variables + for (int i = 0; i < VARIABLES_COUNT; i++) { + log.display(" slot #" + i + ":"); + log.display(" slot: " + indexes[i]); + command.addInt(indexes[i]); + log.display(" slotvalue: " + values[i]); + command.addValue(values[i]); + } + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no data in the reply packet + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + + /** + * Check confiramtion from debuggee that values are changed. + */ + void checkValuesChanged() { + // send debugee signal RUN + log.display("Sending signal to debugee: " + RUN); + pipe.println(RUN); + + // wait for DONE signal from debugee + log.display("Waiting for signal from debugee: " + DONE); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + // check received signal + if (signal == null) { + throw new TestBug(" signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } else if (signal.equals(DONE)) { + log.display("All varaible values have been correctly set into debuggee VM"); + } else if (signal.equals(ERROR)) { + log.complain("Not all variables values have been correctly set into debuggee VM"); + success = false; + } else { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + DONE + ")"); + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/StackFrame/SetValues/setvalues001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: StackFrame + * command: SetValues + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * new values of the method local variables is the same + * as expected. + * Test consists of two compoments: + * debugger: setvalues001 + * debuggee: setvalues001a + * To set values to the method local variables for the current + * thread frame and check that they are set correctly, test defines + * following classes into debuggee VM: + * OriginalValuesClass - class with original values of static fields + * TargetValuesClass - class with target values of static fields + * TestedObjectClass - tested class with tested method with local variables + * TestedThreadClass - thread class with tested frame + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested class + * and object ID and threadID as values of the class static fields. + * Also debugger obtains values of static fields of the class TargetValuesClass + * to use them as new values for local variables from the tested frame. + * Debugger suspends the thread and gets frameID for the current thread + * frameID and indexes of its local variables. Thread is suspended on the + * invokation of the tested method with local variables. + * Then, debugger creates command packet for StackFrame.SetValues + * command with the found threadID, frameID and new values for local + * variables as arguments, writes packet to the transport channel, + * and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts variables values. Debugger checks that no data returmed + * with the reply packet. Also debugger sends debuggee signal RUN to + * to check new values of the local variables. If all values are set + * correctly debuggee replies with the signal DONE. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.StackFrame.SetValues.setvalues001 + * nsk.jdwp.StackFrame.SetValues.setvalues001a + * @comment debuggee should be compiled w/ debug info + * @clean nsk.jdwp.StackFrame.SetValues.setvalues001a + * @compile -g:lines,source,vars ../setvalues001a.java + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.StackFrame.SetValues.setvalues001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.SetValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class setvalues001a { + + // name of the tested object and thread classes + public static final String OBJECT_CLASS_NAME = "TestedObjectClass"; + public static final String THREAD_CLASS_NAME = "TestedThreadClass"; + public static final String THREAD_NAME = "TestedThreadName"; + + // name of the static fields with the tested object values + public static final String THREAD_FIELD_NAME = "thread"; + public static final String OBJECT_FIELD_NAME = "object"; + public static final String OBJECT_METHOD_NAME = "testedMethod"; + + // notification object to notify debuggee that thread is ready + private static Object threadReady = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + setvalues001a _setvalues001a = new setvalues001a(); + System.exit(setvalues001.JCK_STATUS_BASE + _setvalues001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from running further + synchronized (threadLock) { + + // load tested class and create tested thread and object + log.display("Creating object of tested class"); + TestedObjectClass.object = new TestedObjectClass(); + log.display("Creating tested thread"); + TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME); + + OriginalValuesClass original = new OriginalValuesClass(); + TargetValuesClass target = new TargetValuesClass(); + + // start the thread and wait for notification from it + synchronized (threadReady) { + TestedObjectClass.thread.start(); + try { + threadReady.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + setvalues001.READY); + pipe.println(setvalues001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(setvalues001.ERROR); + // exit debuggee + log.complain("Debugee FAILED"); + return setvalues001.FAILED; + } + } + + // wait for signal RUN from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.RUN); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(setvalues001.RUN)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.RUN + ")"); + // skip checking for new values + TestedObjectClass.object.checking = false; + // exit debuggee + log.complain("Debugee FAILED"); + return setvalues001.FAILED; + } + + // allow started thread to run and finish + } + + // wait for tested thread finished + try { + log.display("Waiting for tested thread finished"); + TestedObjectClass.thread.join(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished:\n\t" + + e); + // exit debuggee + log.complain("Debugee FAILED"); + return setvalues001.FAILED; + } + + // confirm that new values of local variables are correct + if (TestedObjectClass.object.different == 0) { + log.display("Sending signal to debugger: " + setvalues001.DONE); + pipe.println(setvalues001.DONE); + } else { + log.complain("Values of " + TestedObjectClass.object.different + + " local variables have not been set correctly"); + log.display("Sending signal to debugger: " + setvalues001.ERROR); + pipe.println(setvalues001.ERROR); + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + setvalues001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(setvalues001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setvalues001.QUIT + ")"); + // exit debuggee + log.complain("Debugee FAILED"); + return setvalues001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return setvalues001.PASSED; + } + + // tested thread class + public static class TestedThreadClass extends Thread { + + public TestedThreadClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // invoke tested method for the tested object from the tested thread + TestedObjectClass.object.testedMethod(); + + log.display("Tested thread finished"); + } + + } + + // tested object class + public static class TestedObjectClass { + + // field with the tested thread and object values + public static volatile TestedThreadClass thread = null; + public static volatile TestedObjectClass object = null; + + // allow to check new values of local variables + public volatile boolean checking = true; + // number of variables with unexpected new values + public volatile int different = 0; + + // tested method with local variables + public void testedMethod() { + + // local variables + boolean booleanValue = OriginalValuesClass.booleanValue; + byte byteValue = OriginalValuesClass.byteValue; + char charValue = OriginalValuesClass.charValue; + int intValue = OriginalValuesClass.intValue; + short shortValue = OriginalValuesClass.shortValue; + long longValue = OriginalValuesClass.longValue; + float floatValue = OriginalValuesClass.floatValue; + double doubleValue = OriginalValuesClass.doubleValue; + String stringValue = OriginalValuesClass.stringValue; + Object objectValue = OriginalValuesClass.objectValue; + + log.display("Tested frame entered"); + + // notify debuggee that tested thread ready for testing + synchronized (threadReady) { + threadReady.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Checking that values have been set correctly:"); + } + + // check new values of local variables + if (checking) { + + // check value of the variable + if (booleanValue != TargetValuesClass.booleanValue) { + different++; + log.complain(" booleanValue = " + booleanValue + "\n" + + " setting: " + OriginalValuesClass.booleanValue + + " -> " + TargetValuesClass.booleanValue); + if (booleanValue == OriginalValuesClass.booleanValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" booleanValue: " + OriginalValuesClass.booleanValue + + " -> " + TargetValuesClass.booleanValue); + } + + // check value of the variable + if (byteValue != TargetValuesClass.byteValue) { + different++; + log.complain(" byteValue = " + byteValue + "\n" + + " setting: " + OriginalValuesClass.byteValue + + " -> " + TargetValuesClass.byteValue); + if (byteValue == OriginalValuesClass.byteValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" byteValue: " + OriginalValuesClass.byteValue + + " -> " + TargetValuesClass.byteValue); + } + + // check value of the variable + if (charValue != TargetValuesClass.charValue) { + different++; + log.complain(" charValue = " + charValue + "\n" + + " setting: " + OriginalValuesClass.charValue + + " -> " + TargetValuesClass.charValue); + if (charValue == OriginalValuesClass.charValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" charValue: " + OriginalValuesClass.charValue + + " -> " + TargetValuesClass.charValue); + } + + // check value of the variable + if (intValue != TargetValuesClass.intValue) { + different++; + log.complain(" intValue = " + intValue + "\n" + + " setting: " + OriginalValuesClass.intValue + + " -> " + TargetValuesClass.intValue); + if (intValue == OriginalValuesClass.intValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" intValue: " + OriginalValuesClass.intValue + + " -> " + TargetValuesClass.intValue); + } + + // check value of the variable + if (shortValue != TargetValuesClass.shortValue) { + different++; + log.complain(" shortValue = " + shortValue + "\n" + + " setting: " + OriginalValuesClass.shortValue + + " -> " + TargetValuesClass.shortValue); + if (shortValue == OriginalValuesClass.shortValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" shortValue: " + OriginalValuesClass.shortValue + + " -> " + TargetValuesClass.shortValue); + } + + // check value of the variable + if (longValue != TargetValuesClass.longValue) { + different++; + log.complain(" longValue = " + longValue + "\n" + + " setting: " + OriginalValuesClass.longValue + + " -> " + TargetValuesClass.longValue); + if (longValue == OriginalValuesClass.longValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" longValue: " + OriginalValuesClass.longValue + + " -> " + TargetValuesClass.longValue); + } + + // check value of the variable + if (floatValue != TargetValuesClass.floatValue) { + different++; + log.complain(" floatValue = " + floatValue + "\n" + + " setting: " + OriginalValuesClass.floatValue + + " -> " + TargetValuesClass.floatValue); + if (floatValue == OriginalValuesClass.floatValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" floatValue: " + OriginalValuesClass.floatValue + + " -> " + TargetValuesClass.floatValue); + } + + // check value of the variable + if (doubleValue != TargetValuesClass.doubleValue) { + different++; + log.complain(" doubleValue = " + doubleValue + "\n" + + " setting: " + OriginalValuesClass.doubleValue + + " -> " + TargetValuesClass.doubleValue); + if (doubleValue == OriginalValuesClass.doubleValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" doubleValue: " + OriginalValuesClass.doubleValue + + " -> " + TargetValuesClass.doubleValue); + } + + // check value of the variable + if (stringValue != TargetValuesClass.stringValue) { + different++; + log.complain(" stringValue = " + stringValue + "\n" + + " setting: " + OriginalValuesClass.stringValue + + " -> " + TargetValuesClass.stringValue); + if (stringValue == OriginalValuesClass.stringValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" stringValue: " + OriginalValuesClass.stringValue + + " -> " + TargetValuesClass.stringValue); + } + + // check value of the variable + if (objectValue != TargetValuesClass.objectValue) { + different++; + log.complain(" objectValue = " + objectValue + "\n" + + " setting: " + OriginalValuesClass.objectValue + + " -> " + TargetValuesClass.objectValue); + if (objectValue == OriginalValuesClass.objectValue) { + log.complain(" not changed!"); + } else { + log.complain(" changed incorrectly!"); + } + } else { + log.display(" objectValue: " + OriginalValuesClass.objectValue + + " -> " + TargetValuesClass.objectValue); + } + } + + log.display("Tested frame dropped"); + } + + } + + // class with the original values of static fields + public static class OriginalValuesClass { + static final boolean booleanValue = true; + static final byte byteValue = (byte)0x01; + static final char charValue = 'Z'; + static final int intValue = 100; + static final short shortValue = (short)10; + static final long longValue = (long)1000000; + static final float floatValue = (float)3.14; + static final double doubleValue = (double)2.8e-12; + static final String stringValue = "text"; + static final Object objectValue = new OriginalValuesClass(); + } + + // class with the original values of static fields + public static class TargetValuesClass { + static final boolean booleanValue = false; + static final byte byteValue = (byte)0x0F; + static final char charValue = 'A'; + static final int intValue = 999; + static final short shortValue = (short)88; + static final long longValue = (long)11111111; + static final float floatValue = (float)7.19; + static final double doubleValue = (double)4.6e24; + static final String stringValue = "new text"; + static final Object objectValue = new TargetValuesClass(); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.ThisObject; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: StackFrame.ThisObject. + * + * See thisobject001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class thisobject001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.StackFrame.ThisObject"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "thisobject001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "StackFrame.ThisObject"; + static final int JDWP_COMMAND_ID = JDWP.Command.StackFrame.ThisObject; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + thisobject001a.OBJECT_CLASS_NAME; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // names of the static fields with the tested thread and object values + static final String TESTED_OBJECT_FIELD_NAME = thisobject001a.OBJECT_FIELD_NAME; + static final String TESTED_THREAD_FIELD_NAME = thisobject001a.THREAD_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new thisobject001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectID value from static field + log.display("Getting objectID value from static field: " + + TESTED_OBJECT_FIELD_NAME); + long objectID = queryObjectID(classID, TESTED_OBJECT_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // query debuggee for threadID value from static field + log.display("Getting threadID value from static field: " + + TESTED_THREAD_FIELD_NAME); + threadID = queryObjectID(classID, TESTED_THREAD_FIELD_NAME, JDWP.Tag.THREAD); + log.display(" got threadID: " + threadID); + + // suspend tested thread into debuggee + log.display("Suspending thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + + // query debuggee for current frameID of the tested thread + log.display("Getting current frameID for the threadID: " + + threadID); + long frameID = debugee.getCurrentFrameID(threadID); + log.display(" got frameID: " + frameID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(frameID, threadID, objectID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static field of the class. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has expected tag + if (value.getTag() != tag) { + throw new Failure("Unexpected tag for object value returned: " + + value.getTag() + " (expected: " + tag + ")"); + } + + // extract objectID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified frameID. + */ + void testCommand(long frameID, long threadID, long expectedObjectID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" frameID: " + frameID); + command.addFrameID(frameID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract tag of object value + byte tag = (byte)0; + try { + tag = reply.getByte(); + log.display(" tag: " + tag); + } catch (BoundException e) { + log.complain("Unable to extract object tag from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract objectID of object value + long objectID = 0; + try { + objectID = reply.getObjectID(); + log.display(" objectID: " + objectID); + } catch (BoundException e) { + log.complain("Unable to extract objectID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that object tag is as expected + if (tag != JDWP.Tag.OBJECT) { + log.complain("Unexpected object tag returned: " + + tag + " (expected: " + JDWP.Tag.OBJECT + ")"); + success = false; + } + + // check that objectID is as expected + if (objectID < 0) { + log.complain("Negative value of objectID retured: " + + objectID + " (expected: " + expectedObjectID + ")"); + success = false; + } else if (objectID != expectedObjectID) { + log.complain(" Unexpected objectID retured: " + + objectID + " (expected: " + expectedObjectID + ")"); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/StackFrame/ThisObject/thisobject001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: StackFrame + * command: ThisObject + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned objectID for current test frame is the same as expected. + * Test consists of two compoments: + * debugger: thisobject001 + * debuggee: thisobject001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested class + * and object ID and threadID as values of the class static fields. + * Also debugger suspends the thread and gets frameID for the + * current thread frameID. Thread is suspended on the invokation + * of method of the tested object. + * Then, debugger creates command packet for StackFrame.ThisObject + * command with the found threadID and frameID as arguments, writes + * packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts requested objectID. Also test checks that returned objectID + * has the expected tag and value. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.StackFrame.ThisObject.thisobject001 + * nsk.jdwp.StackFrame.ThisObject.thisobject001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.StackFrame.ThisObject.thisobject001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StackFrame.ThisObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class thisobject001a { + + // name of the tested object and thread classes + public static final String OBJECT_CLASS_NAME = "TestedObjectClass"; + public static final String THREAD_CLASS_NAME = "TestedThreadClass"; + public static final String THREAD_NAME = "TestedThreadName"; + + // name of the static fields with the tested object values + public static final String THREAD_FIELD_NAME = "thread"; + public static final String OBJECT_FIELD_NAME = "object"; + + // notification object to notify debuggee that thread is ready + private static Object threadReady = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + thisobject001a _thisobject001a = new thisobject001a(); + System.exit(thisobject001.JCK_STATUS_BASE + _thisobject001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread and object + log.display("Creating object of tested class"); + TestedObjectClass.object = new TestedObjectClass(); + log.display("Creating tested thread"); + TestedObjectClass.thread = new TestedThreadClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadReady) { + TestedObjectClass.thread.start(); + try { + threadReady.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + thisobject001.READY); + pipe.println(thisobject001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(thisobject001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + thisobject001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(thisobject001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + thisobject001.QUIT + ")"); + log.complain("Debugee FAILED"); + return thisobject001.FAILED; + } + + // allow started thread to finish + } + + // wait for tested thread finished + try { + log.display("Waiting for tested thread finished"); + TestedObjectClass.thread.join(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished:\n\t" + + e); + log.complain("Debugee FAILED"); + return thisobject001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return thisobject001.PASSED; + } + + // tested thread class + public static class TestedThreadClass extends Thread { + + TestedThreadClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // invoke tested method for the tested object from the tested thread + int foo = 100; + TestedObjectClass.object.testedMethod(foo); + + log.display("Tested thread finished"); + } + + } + + // tested object class + public static class TestedObjectClass { + + // field with the tested thread and object values + public static volatile TestedThreadClass thread = null; + public static volatile TestedObjectClass object = null; + + public void testedMethod(int foo) { + log.display("Tested frame entered"); + + // local variables + int boo = foo; + + // notify debuggee that tested thread ready for testing + synchronized (threadReady) { + threadReady.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested frame dropped"); + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StringReference.Value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; +import java.util.*; + +public class value001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.StringReference.Value"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "value001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "StringReference.Value"; + static final int JDWP_COMMAND_ID = JDWP.Command.StringReference.Value; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new value001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + try { + + // create string in debugee + + String originalStringValue = "Testing string value"; + long stringID = 0; + + { + // Suspend debuggee to avoid GC + log.display("Suspending debuggee"); + debugee.suspend(); + log.display("Debuggee suspended"); + + log.display("Create command packet" + "CreateString" + + " with string value: " + originalStringValue); + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.CreateString); + command.addString(originalStringValue); + command.setLength(); + + log.display("Waiting for reply to command"); + ReplyPacket reply = debugee.receiveReplyFor(command); + log.display("Valid reply packet received"); + + log.display("Parsing reply packet"); + reply.resetPosition(); + + stringID = reply.getObjectID(); + log.display(" stringID: " + stringID); + + // Disable garbage collection of the String + log.display("Disabling collection of String object"); + command = new CommandPacket(JDWP.Command.ObjectReference.DisableCollection); + command.addObjectID(stringID); + command.setLength(); + reply = debugee.receiveReplyFor(command); + reply.resetPosition(); + log.display("Collection disabled"); + + // Resume debugee now that we have disabled collection of the String + log.display("Resuming debuggee"); + debugee.resume(); + log.display("Debuggee resumed"); + } + + // begint test of JDWP command + + log.display("Create command packet" + JDWP_COMMAND_NAME + + "with stringID: " + stringID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(stringID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String stringValue = reply.getString(); + log.display(" stringValue: " + stringValue); + + if (! stringValue.equals(originalStringValue)) { + log.complain("Received value does not equals original value:" + + originalStringValue); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + // end test of JDWP command + + // Re-enable garbage collection of the String + log.display("Enabling collection of String object"); + command = new CommandPacket(JDWP.Command.ObjectReference.EnableCollection); + command.addObjectID(stringID); + command.setLength(); + reply = debugee.receiveReplyFor(command); + reply.resetPosition(); + log.display("Collection enabled"); + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/StringReference/Value/value001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: StringReference + * command: Value + * Test checks that debugee accept command and replies + * with correct reply packet. Also test checks that + * returned value of the requested string is equal + * to the expected one. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test queries debugee VM to create string with given vaule + * and saves stringID of created string. + * Then test sends Value command with saved stringID + * as an command argument and waits for a reply packet. + * Then test checks if the received reply packet has proper + * structure and extracted string value is equal to + * the expected string. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.StringReference.Value.value001 + * nsk.jdwp.StringReference.Value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.StringReference.Value.value001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.StringReference.Value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class value001a { + + public static void main(String args[]) { + value001a _value001a = new value001a(); + System.exit(value001.JCK_STATUS_BASE + _value001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return value001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadGroupReference.Children; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class children001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ThreadGroupReference.Children"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "children001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ThreadGroupReference.Children"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadGroupReference.Children; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new children001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + + try { + + // get top level thread groups + + log.display("Getting IDs for top level thread groups"); + + long[] threadGroupIDs = null; + int groups = 0; + + { + log.display("Create command packet " + "TopLevelThreadGroups"); + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.TopLevelThreadGroups); + + log.display("Waiting for reply to command"); + ReplyPacket reply = debugee.receiveReplyFor(command); + log.display("Valid reply packet received"); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + groups = reply.getInt(); + log.display(" groups: " + groups); + + threadGroupIDs = new long[groups]; + + for (int i = 0; i < groups; i++) { + long threadGroupID = reply.getObjectID(); + log.display(" " + i + " threadGroupID: " + threadGroupID); + threadGroupIDs[i] = threadGroupID; + } + + if (groups < 0) { + log.complain("Negative number of thread groups returned while getting top level thread groups IDs: " + groups); + success = false; + } + + if (groups == 0) { + log.complain("No thread groups IDs returned while getting top level thread groups IDs: " + groups); + success = false; + } + + } + + // begin test of JDWP command + + for (int i = 0; i < groups; i++) { + + long threadGroupID = threadGroupIDs[i]; + + log.display("Getting name for " + i + " group ID: " + + threadGroupID); + + log.display("Create command " + JDWP_COMMAND_NAME + + " with thread group ID: " + threadGroupID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadGroupID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int childThreads = reply.getInt(); + log.display(" childThreads: " + childThreads); + + for (int j = 0; j < childThreads; j++) { + long childThread = reply.getObjectID(); + log.display(" " + j + " childThread: " + childThread); + } + + int childGroups = reply.getInt(); + log.display(" childGroups: " + childGroups); + + for (int j = 0; j < childGroups; j++) { + long childGroup = reply.getObjectID(); + log.display(" " + j + " childGroup: " + childGroup); + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadGroupReference/Children/children001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadGroupReference + * command: Children + * Test checks that debugee accepts command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test queries debugee VM for ThreadGroupReferenceIDs + * of all top level thread groups. + * Then test sends Children command for each ThreadGroupReferenceID + * and waits for a reply packet. + * Test checks if the each received reply packet has proper + * structure and extract childs info of the queried thread group. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadGroupReference.Children.children001 + * nsk.jdwp.ThreadGroupReference.Children.children001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadGroupReference.Children.children001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadGroupReference.Children; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class children001a { + + public static void main(String args[]) { + children001a _children001a = new children001a(); + System.exit(children001.JCK_STATUS_BASE + _children001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return children001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadGroupReference.Name; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class name001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ThreadGroupReference.Name"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "name001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ThreadGroupReference.Name"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadGroupReference.Name; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new name001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + + try { + + // get top level thread groups + + log.display("Getting IDs for top level thread groups"); + + long[] threadGroupIDs = null; + int groups = 0; + + { + log.display("Create command packet " + "TopLevelThreadGroups"); + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.TopLevelThreadGroups); + + log.display("Waiting for reply to command"); + ReplyPacket reply = debugee.receiveReplyFor(command); + log.display("Valid reply packet received"); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + groups = reply.getInt(); + log.display(" groups: " + groups); + + threadGroupIDs = new long[groups]; + + for (int i = 0; i < groups; i++) { + long threadGroupID = reply.getObjectID(); + log.display(" " + i + " threadGroupID: " + threadGroupID); + threadGroupIDs[i] = threadGroupID; + } + + if (groups < 0) { + log.complain("Negative number of thread groups returned while getting top level thread groups IDs: " + groups); + success = false; + } + + if (groups == 0) { + log.complain("No thread groups IDs returned while getting top level thread groups IDs: " + groups); + success = false; + } + + } + + // begin test of JDWP command + + for (int i = 0; i < groups; i++) { + + long threadGroupID = threadGroupIDs[i]; + + log.display("Getting name for " + i + " group ID: " + + threadGroupID); + + log.display("Create command " + JDWP_COMMAND_NAME + + " with thread group ID: " + threadGroupID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadGroupID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String groupName = reply.getString(); + log.display(" groupName: " + groupName); + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadGroupReference/Name/name001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadGroupReference + * command: Name + * Test checks that debugee accepts command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test queries debugee VM for ThreadGroupReferenceIDs + * of all top level thread groups. + * Then test sends Name command for each ThreadGroupReferenceID + * and waits for a reply packet. + * Test checks if the each received reply packet has proper + * structure and extract name of the queried thread group. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadGroupReference.Name.name001 + * nsk.jdwp.ThreadGroupReference.Name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadGroupReference.Name.name001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadGroupReference.Name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class name001a { + + public static void main(String args[]) { + name001a _name001a = new name001a(); + System.exit(name001.JCK_STATUS_BASE + _name001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return name001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadGroupReference.Parent; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class parent001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ThreadGroupReference.Parent"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "parent001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ThreadGroupReference.Parent"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadGroupReference.Parent; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new parent001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + + try { + + // get top level thread groups + + log.display("Getting IDs for top level thread groups"); + + long[] threadGroupIDs = null; + int groups = 0; + + { + log.display("Create command packet " + "TopLevelThreadGroups"); + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.TopLevelThreadGroups); + + log.display("Waiting for reply to command"); + ReplyPacket reply = debugee.receiveReplyFor(command); + log.display("Valid reply packet received"); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + groups = reply.getInt(); + log.display(" groups: " + groups); + + threadGroupIDs = new long[groups]; + + for (int i = 0; i < groups; i++) { + long threadGroupID = reply.getObjectID(); + log.display(" " + i + " threadGroupID: " + threadGroupID); + threadGroupIDs[i] = threadGroupID; + } + + if (groups < 0) { + log.complain("Negative number of thread groups returned while getting top level thread groups IDs: " + groups); + success = false; + } + + if (groups == 0) { + log.complain("No thread groups IDs returned while getting top level thread groups IDs: " + groups); + success = false; + } + + } + + // begin test of JDWP command + + for (int i = 0; i < groups; i++) { + + long threadGroupID = threadGroupIDs[i]; + + log.display("Getting name for " + i + " group ID: " + + threadGroupID); + + log.display("Create command " + JDWP_COMMAND_NAME + + " with thread group ID: " + threadGroupID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadGroupID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long parentGroup = reply.getObjectID(); + log.display(" parentGroup: " + parentGroup); + + if (parentGroup != 0) { + log.complain("Nonzero ThreadGroupID of parent thread group returned for top-level thread group"); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadGroupReference/Parent/parent001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadGroupReference + * command: Parent + * Test checks that debugee accepts command and replies + * with correct reply packet. Also test check that returned + * parent ThreadGroupID for top-level group is equal to zero. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test queries debugee VM for ThreadGroupReferenceIDs + * of all top level thread groups. + * Then test sends Parent command for each ThreadGroupReferenceID + * and waits for a reply packet. + * Test checks if the each received reply packet has proper + * structure and extract childs info of the queried thread group. + * Also test check that extracted parent ThreadGroupID for + * top-level group is equal to zero. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadGroupReference.Parent.parent001 + * nsk.jdwp.ThreadGroupReference.Parent.parent001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadGroupReference.Parent.parent001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadGroupReference.Parent; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class parent001a { + + public static void main(String args[]) { + parent001a _parent001a = new parent001a(); + System.exit(parent001.JCK_STATUS_BASE + _parent001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return parent001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.CurrentContendedMonitor; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.CurrentContendedMonitor. + * + * See curcontmonitor001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class curcontmonitor001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.CurrentContendedMonitor"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "curcontmonitor001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_GET_CURRENT_CONTENDED_MONITOR; + static final String VM_CAPABILITY_NAME = "canGetCurrentContendedMonitor"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.CurrentContendedMonitor"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.CurrentContendedMonitor; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_THREAD_NAME = curcontmonitor001a.THREAD_NAME; + static final String THREAD_FIELD_NAME = curcontmonitor001a.THREAD_FIELD_NAME; + static final String MONITOR_FIELD_NAME = curcontmonitor001a.MONITOR_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new curcontmonitor001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Checking VM capability \n"); + + // check for VM capability + log.display("Checking VM capability: " + VM_CAPABILITY_NAME); + if (!debugee.getCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME)) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + THREAD_FIELD_NAME); + threadID = queryObjectID(classID, THREAD_FIELD_NAME, JDWP.Tag.THREAD); + log.display(" got threadID: " + threadID); + + // query debuggee for objectID value for owned monitor from a static field + log.display("Getting objectID value for owned monitor from static field: " + + MONITOR_FIELD_NAME); + long monitorID = queryObjectID(classID, + MONITOR_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + monitorID); + + // suspend all threads into debuggee + log.display("Suspending all threads into debuggee"); + debugee.suspend(); + log.display(" debuggee suspended"); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID, monitorID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume all threads into debuggee + log.display("resuming all threads into debuggee"); + debugee.resume(); + log.display(" debuggee resumed"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID, long monitorID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract object tag + byte tag = (byte)0; + try { + tag = reply.getByte(); + log.display(" tag: " + tag); + } catch (BoundException e) { + log.complain("Unable to extract tag for contended monitor object from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract objectID + long objectID = 0; + try { + objectID = reply.getObjectID(); + log.display(" objectID: " + objectID); + } catch (BoundException e) { + log.complain("Unable to extract contended monitor objectID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that tag is an OBJECT tag + if (tag != JDWP.Tag.OBJECT) { + log.complain("Unexpected tag for monitor object received:" + tag + + " (expected" + JDWP.Tag.OBJECT); + success = false; + } + + // check that objectID is not negative integer + if (objectID < 0) { + log.complain("Negative value of objectID received: " + objectID); + success = false; + } + + // check that objectID is as expected + if (objectID != monitorID) { + log.display("Unexpected monitor objectID received: " + objectID + + " (expected" + monitorID); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: CurrentContendedMonitor + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that the expected objectID of monitor object + * returned for the tested thread. + * Test consists of two compoments: + * debugger: curcontmonitor001 + * debuggee: curcontmonitor001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Also debugger + * suspends the thread before sending the tested command. The tested + * thread is waiting for the object at this moment. + * Then, debugger creates command packet for ThreadReference.CurrenContendedMonitor + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts objectID for the thread current contended monitor. Also + * test checks that the extracted objectID is equals to the expected one. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * For JDK 1.4.0-beta3 (build 1.4.0-beta3-b84) and earlier this test passed + * because target VM does not support VM capability: canGetCurrentContendedMonitor + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.CurrentContendedMonitor.curcontmonitor001 + * nsk.jdwp.ThreadReference.CurrentContendedMonitor.curcontmonitor001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.CurrentContendedMonitor.curcontmonitor001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.CurrentContendedMonitor; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class curcontmonitor001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String THREAD_FIELD_NAME = "thread"; + public static final String MONITOR_FIELD_NAME = "monitor"; + + // frames count for tested thread in recursive method invokation + public static final int FRAMES_COUNT = 10; + + // notification object to notify debuggee that thread is started + private static Object threadStarting = new Object(); + // object which thread will wait for before being interruted + private static Object threadWaiting = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + curcontmonitor001a _curcontmonitor001a = new curcontmonitor001a(); + System.exit(curcontmonitor001.JCK_STATUS_BASE + _curcontmonitor001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarting) { + TestedClass.thread.start(); + try { + threadStarting.wait(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started:\n\t" + e); + pipe.println(curcontmonitor001.ERROR); + log.display("Debugee FAILED"); + return curcontmonitor001.FAILED; + } + + // ensure that tested thread is waiting for monitor object + synchronized (TestedClass.thread.monitor) { + // send debugger signal READY + log.display("Sending signal to debugger: " + curcontmonitor001.READY); + pipe.println(curcontmonitor001.READY); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + curcontmonitor001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // interrupt waiting thread + log.display("Interrupting tested thread being waited"); + TestedClass.thread.interrupt(); + + // check received signal + if (signal == null || !signal.equals(curcontmonitor001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + curcontmonitor001.QUIT + ")"); + log.display("Debugee FAILED"); + return curcontmonitor001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return curcontmonitor001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + // field with monitor object which thread will infinitively wait for + public static volatile Object monitor = new Object(); + + public TestedClass(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display("Tested thread started"); + + synchronized (monitor) { + + // notify debuggee that thread started + synchronized (threadStarting) { + threadStarting.notifyAll(); + } + + // wait infinitely for monitor object + try { + monitor.wait(); + } catch (InterruptedException e) { + log.display("Tested thread interrupted"); + } + } + + log.display("Tested thread finished"); + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001. + * VM Testbase keywords: [jpda, jdwp, feature_jdk6_jpda, vm6, monitoring, quarantine] + * VM Testbase comments: JDK-7199837 + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: ForceEarlyReturn + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: forceEarlyReturn001 + * debuggee: forceEarlyReturn001a + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Debuggee VM create thread(class nsk.share.jpda.ForceEarlyReturnTestThread is used) which sequentially call + * test methods with different return value's type: + * - void + * - all primitive types + * - all wrappers of primitive types + * - String + * - Object + * - array of java.lang.Object + * - Thread + * - ThreadGroup + * - Class object + * - ClassLoader + * Also test thread class contains static fields with predefined values which should be returned through + * ForceEarlyReturn('expectedXXXValue') and fields with values which can be used to check is ForceEarlyReturn returns + * TYPE_MISMATCH error if value's type in command doesn't match method's return type('invalidXXXValue'). + * Debugger set breakpoints in test thread's methods and create instances of 'nsk.share.jdwp.JDWP.Value' + * based on values predefined in ForceEarlyReturnTestThread (both valid and invalid values are created). + * Debugger obtains threadID for test thread. + * Debugger force debugee start test thread and wait while BreakpointEvents occurs. When debuggee's + * test thread stop at breakpoint debugger first creates command packet for ForceEarlyReturn command with the + * found threadID and corresponding instance of invalid 'nsk.share.jdwp.JDWP.Value', writes + * packet to the transport channel, and waits for a reply packet. When reply packet is received, debugger + * parses the packet structure and checks that reply contain TYPE_MISMATCH error. Then debugger send command + * with correct value, checks that reply is empty and resume debuggee VM. + * Test thread in debuggee VM checks that value returned from test methods equals predefined value and no + * instructions was executed in called method after force return (finally blocks are not executed too). + * When all breakpoint events occured debugger sends debuggee signal to finish test thread execution. + * Debuggee waits when test thread finish execution and checks is any errors occured during test. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; +import nsk.share.jdwp.JDWP.Value; +import nsk.share.jpda.ForceEarlyReturnTestThread; + +public class forceEarlyReturn001 +extends TestDebuggerType1 +{ + // data needed to create JDWP command, + // also this class create breakpoint in method which should be forced to return + class TestData + { + public TestData(long classID, String methodName, int lineNumber, long threadID, Value value, Value invalidValue) + { + breakpointID = debuggee.requestBreakpointEvent( + JDWP.TypeTag.CLASS, + classID, + debuggee.getMethodID(classID, methodName, true), + lineNumber, + JDWP.SuspendPolicy.EVENT_THREAD); + + this.value = value; + this.invalidValue = invalidValue; + this.threadID = threadID; + } + + public int breakpointID; + public Value value; + public Value invalidValue; + public long threadID; + } + + protected String getDebugeeClassName() + { + return "nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a"; + } + + public static void main (String argv[]) + { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) + { + return new forceEarlyReturn001().runIt(argv, out); + } + + // send command and receive empty reply + // all asserts should be done in debuggee + private void sendCommand(long threadID, Value value, boolean expectError, int errorCode) + { + try + { + int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.ForceEarlyReturn; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("threadID = " + threadID); + log.display("Value = " + value); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadID); + command.addValue(value); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command, expectError, errorCode); + + if(expectError) + return; + + log.display("Empty reply"); + + if(!reply.isParsed()) + { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } + catch(Exception e) + { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + private TestData[] testData; + + // create Value objects which should be send in command packet and + // initialize breapoints in tested methods + private void initTestData() + { + long classID = debuggee.getReferenceTypeID(createTypeSignature(ForceEarlyReturnTestThread.class.getName())); + + Value testValues[] = new Value[ForceEarlyReturnTestThread.testedTypesNames.length + 1]; + Value testInvalidValues[] = new Value[ForceEarlyReturnTestThread.testedTypesNames.length + 1]; + + testValues[0] = new JDWP.Value(JDWP.Tag.VOID, new Long(0)); + + for(int i = 1; i < ForceEarlyReturnTestThread.testedTypesNames.length; i++) + { + testValues[i] = debuggee.getStaticFieldValue( + classID, + debuggee.getClassFieldID(classID, "expected" + ForceEarlyReturnTestThread.testedTypesNames[i] + "Value", true)); + } + + for(int i = 0; i < ForceEarlyReturnTestThread.testedTypesNames.length; i++) + { + testInvalidValues[i] = debuggee.getStaticFieldValue( + classID, + debuggee.getClassFieldID(classID, "invalid" + ForceEarlyReturnTestThread.testedTypesNames[i] + "Value", true)); + } + + long threadID = debuggee.getThreadID(forceEarlyReturn001a.testThreadName); + + testData = new TestData[ForceEarlyReturnTestThread.testedTypesNames.length]; + + for(int i = 0; i < ForceEarlyReturnTestThread.testedTypesNames.length; i++) + { + testData[i] = new TestData(classID, + ForceEarlyReturnTestThread.testedTypesNames[i] + "Method", + ForceEarlyReturnTestThread.breakpointLines[i], + threadID, + testValues[i], + testInvalidValues[i]); + } + } + + public void doTest() + { + initTestData(); + + pipe.println(forceEarlyReturn001a.COMMAND_START_EXECUTION); + + if(!isDebuggeeReady()) + return; + + for(int i = 0; i < testData.length; i++) + { + // wait when tested thread call method with breapoint + debuggee.waitForBreakpointEvent(testData[i].breakpointID); + + log.display("Send invalid command: valid value: " + testData[i].value + " invalid value: " + testData[i].invalidValue); + // send ForceEarlyReturn command with invalid value + sendCommand(testData[i].threadID, testData[i].invalidValue, true, JDWP.Error.TYPE_MISMATCH); + + log.display("Send valid command: valid value: " + testData[i].value); + // send ForceEarlyReturn command + sendCommand(testData[i].threadID, testData[i].value, false, 0); + + // resume debuggee + debuggee.resume(); + } + + pipe.println(forceEarlyReturn001a.COMMAND_END_EXECUTION); + + if(!isDebuggeeReady()) + return; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001; + +import nsk.share.TestBug; +import nsk.share.jdwp.*; +import nsk.share.jpda.ForceEarlyReturnTestThread; + +public class forceEarlyReturn001a extends AbstractJDWPDebuggee { + public static String testThreadName = "ForceEarlyReturnTestThread"; + + private ForceEarlyReturnTestThread testThread; + + protected void init(String args[]) { + super.init(args); + + // create instance of ForceEarlyReturnTestThread during initialization + // to let debugger obtain threadID for this thread + testThread = new ForceEarlyReturnTestThread(log, true, 1); + testThread.setName(testThreadName); + testThread.start(); + } + + public static String COMMAND_START_EXECUTION = "startExecution"; + + public static String COMMAND_END_EXECUTION = "endExecution"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + // force ForceEarlyReturnTestThread start execution + if (command.equals(COMMAND_START_EXECUTION)) { + testThread.startExecuion(); + return true; + } else + // wait when ForceEarlyReturnTestThread finish execution and check + // is any errors occured during test + if (command.equals(COMMAND_END_EXECUTION)) { + try { + testThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + throw new TestBug("Unexpected exception: " + e); + } + + if (!testThread.getSuccess()) { + setSuccess(false); + } + + return true; + } + + return false; + } + + public static void main(String args[]) { + new forceEarlyReturn001a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: ForceEarlyReturn + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: forceEarlyReturn002 + * debuggee: forceEarlyReturn002a + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Test performs checks for cases when incorrect data are send in command. + * Following cases are tested: + * - create command with threadID = 1, expect INVALID_OBJECT error + * - debuggee creates test thread which sequentially changes its state in following order: + * - thread not started + * - thread is running + * - thread is sleeping + * - thread in Object.wait() + * - thread wait on java monitor + * - thread is finished + * Debugger try execute command for this thread without thread suspending for states: thread running, thread sleeping, + * thread waiting, thread blocked, THREAD_NOT_SUSPENDED error is expected. + * When test thread has finish execution debugger suspends thread and call command for this thread, INVALID_THREAD + * error is expected, then, debugger resumes test thread and call command again, INVALID_THREAD error should + * be returned in reply. + * - debuggee starts test thread which executes infinite loop in native method, debugger calls command for + * this thread(without suspending) and expects THREAD_NOT_SUSPENDED error. Then, debugger suspends this thread + * and calls command again, OPAQUE_FRAME error is expected. + * - debugger creates ThreadStartEventRequest with suspend policy 'JDWP.SuspendPolicy.ALL' and forces debuggee start new thread. + * When ThreadStartEvent is received debugger obtains threadID from this event and calls command for this thread. Since + * just started thread has no frames yet NO_MORE_FRAMES error is expected. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn002; + +import java.io.*; + +import nsk.share.Consts; +import nsk.share.jdwp.*; +import nsk.share.jdwp.JDWP.Value; +import nsk.share.jpda.AbstractDebuggeeTest; +import nsk.share.jpda.StateTestThread; + +public class forceEarlyReturn002 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return "nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002a"; + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn002().runIt(argv, out); + } + + private void sendCommand(long threadID, Value value, boolean expectError, int errorCode) { + try { + int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.ForceEarlyReturn; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("threadID = " + threadID); + log.display("Value = " + value); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadID); + command.addValue(value); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command, expectError, errorCode); + + if (expectError) + return; + + log.display("Empty reply"); + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + private int createThreadStartEventRequest() { + try { + // create command packet and fill requred out data + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + command.addByte(JDWP.EventKind.THREAD_START); + command.addByte(JDWP.SuspendPolicy.ALL); + command.addInt(0); + command.setLength(); + + transport.write(command); + + ReplyPacket reply; + reply = getReply(command); + + int requestID = reply.getInt(); + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in request reply packet at: " + reply.offsetString()); + return -1; + } + + return requestID; + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + + return -1; + } + } + + public void doTest() { + Value value; + + value = new Value(JDWP.Tag.INT, 0); + // create command with invalid trheadID, expect INVALID_OBJECT error + sendCommand(-1, value, true, JDWP.Error.INVALID_OBJECT); + + // create StateTestThread + pipe.println(AbstractDebuggeeTest.COMMAND_CREATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + // switch thread state to RUNNING to get threadID (can't get threadID + // when thread not running) + pipe.println(AbstractDebuggeeTest.COMMAND_NEXTSTATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + long threadID = debuggee.getThreadID(AbstractDebuggeeTest.stateTestThreadName); + + int state = 2; + + // check following states: "RUNNING", "SLEEPING", "WAIT", "MONITOR" + while (state++ < StateTestThread.stateTestThreadStates.length) { + sendCommand(threadID, value, true, JDWP.Error.THREAD_NOT_SUSPENDED); + + pipe.println(AbstractDebuggeeTest.COMMAND_NEXTSTATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + } + + // here thread has exited (state "ZOMBIE") + sendCommand(threadID, value, true, JDWP.Error.INVALID_THREAD); + + // suspend thread, but also expect INVALID_THREAD error + debuggee.suspendThread(threadID); + sendCommand(threadID, value, true, JDWP.Error.INVALID_THREAD); + + // create thread which executes native method + pipe.println(forceEarlyReturn002a.COMMAND_STOP_THREAD_IN_NATIVE); + + if (!isDebuggeeReady()) + return; + + threadID = debuggee.getThreadID(forceEarlyReturn002a.testThreadInNativeName); + + // thread in native not suspended, expect THREAD_NOT_SUSPENDED error + sendCommand(threadID, value, true, JDWP.Error.THREAD_NOT_SUSPENDED); + + debuggee.suspendThread(threadID); + // suspended thread in native, expect OPAQUE_FRAME error + sendCommand(threadID, value, true, JDWP.Error.OPAQUE_FRAME); + + // create request for ThreadStart event + int requestID = createThreadStartEventRequest(); + + // force debuggee start new thread + pipe.println(forceEarlyReturn002a.COMMAND_START_NEW_THREAD); + + // receive ThreadStart event + EventPacket eventPacket = receiveSingleEvent(JDWP.EventKind.THREAD_START, requestID); + + try { + threadID = eventPacket.getObjectID(); + + value = new Value(JDWP.Tag.VOID, 0); + // just started thread has no frames, expect NO_MORE_FRAMES error + sendCommand(threadID, value, true, JDWP.Error.NO_MORE_FRAMES); + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + + clearRequest(JDWP.EventKind.THREAD_START, requestID); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn002; + +import nsk.share.Consts; +import nsk.share.jdwp.*; + +public class forceEarlyReturn002a extends AbstractJDWPDebuggee { + static { + try { + System.loadLibrary("forceEarlyReturn002a"); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError when load library 'forceEarlyReturn002a'"); + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + public final static String testThreadInNativeName = "forceEarlyReturn002aTestThreadInNative"; + + public final static String COMMAND_STOP_THREAD_IN_NATIVE = "stopInNative"; + + public final static String COMMAND_START_NEW_THREAD = "startNewThread"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_STOP_THREAD_IN_NATIVE)) { + stopThreadInNative(); + + return true; + } else if (command.equals(COMMAND_START_NEW_THREAD)) { + Thread thread = new Thread(new Runnable() { + public void run() { + log.display("Thread exit"); + } + }); + + thread.setName("forceEarlyReturn002a_NewThread"); + thread.start(); + + return true; + } + + return false; + } + + private Thread testThreadInNative; + + private void stopThreadInNative() { + testThreadInNative = new Thread(new Runnable() { + public void run() { + Thread.currentThread().setName(testThreadInNativeName); + log.display("Enter native method"); + nativeMethod(forceEarlyReturn002a.this); + } + }); + + testThreadInNative.start(); + + while (!threadInNative) + Thread.yield(); + } + + public volatile boolean threadInNative; + + private static native int nativeMethod(Object object); + + public static void main(String args[]) { + new forceEarlyReturn002a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/libforceEarlyReturn002a.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/libforceEarlyReturn002a.c Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_PTR + +#ifdef __cplusplus +#define JNI_ENV_ARG_2(x, y) y +#define JNI_ENV_ARG_3(x, y, z) y, z +#define JNI_ENV_ARG_4(x, y, z, a) y, z, a +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG_2(x,y) x, y +#define JNI_ENV_ARG_3(x, y, z) x, y, z +#define JNI_ENV_ARG_4(x, y, z, a) x, y, z, a +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +int always_true = 1; + +JNIEXPORT jint JNICALL +Java_nsk_jdwp_ThreadReference_ForceEarlyReturn_forceEarlyReturn002_forceEarlyReturn002a_nativeMethod(JNIEnv *env, jobject classObject, jobject object) +{ + int dummy_counter = 0; + // notify another thread that thread in native method + jclass klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, object)); + jfieldID field = JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG_4(env, klass, "threadInNative", "Z")); + JNI_ENV_PTR(env)->SetBooleanField(JNI_ENV_ARG_4(env, object, field, 1)); + + // execute infinite loop to be sure that thread in native method + while(always_true) + { + // Need some dummy code so the optimizer does not remove this loop. + dummy_counter = dummy_counter < 1000 ? 0 : dummy_counter + 1; + } + // The optimizer can be surprisingly clever. + // Use dummy_counter so it can never be optimized out. + // This statement will always return 0. + return dummy_counter >= 0 ? 0 : 1; +} + +#ifdef __cplusplus +} +#endif diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.FrameCount; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.FrameCount. + * + * See framecnt001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class framecnt001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.FrameCount"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "framecnt001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.FrameCount"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.FrameCount; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = framecnt001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = framecnt001a.THREAD_NAME; + + // expected number of frames count + static final int FRAMES_COUNT = framecnt001a.FRAMES_COUNT; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new framecnt001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // suspend tested thread into debyggee + log.display("Suspending thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract frames count + int frameCount = 0; + try { + frameCount = reply.getInt(); + log.display(" frameCount: " + frameCount); + } catch (BoundException e) { + log.complain("Unable to extract frames count from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that frames count is not negative + if (frameCount < 0) { + log.complain("Negative value of frames count in reply packet: " + + frameCount); + success = false; + } + + // check that thread has an expected state + if (frameCount != FRAMES_COUNT) { + log.complain("Unexpected number of frames count returned: " + + frameCount + " (expected: " + FRAMES_COUNT + ")"); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/FrameCount/framecnt001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: FrameCount + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned number of thread frames is the same as expected. + * Test consists of two compoments: + * debugger: framecnt001 + * debuggee: framecnt001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Also debugger + * suspends the thread before sending the tested command. + * Then, debugger creates command packet for ThreadReference.FrameCount + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of frames in the thread. Also test checks that + * returned frames count is not negative and has the expected value. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.FrameCount.framecnt001 + * nsk.jdwp.ThreadReference.FrameCount.framecnt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.FrameCount.framecnt001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.FrameCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class framecnt001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + // frames count for tested thread in recursive method invokation + public static final int FRAMES_COUNT = 10; + + // notification object to notify debuggee that thread is ready + private static Object threadReady = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + framecnt001a _framecnt001a = new framecnt001a(); + System.exit(framecnt001.JCK_STATUS_BASE + _framecnt001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadReady) { + TestedClass.thread.start(); + try { + threadReady.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + framecnt001.READY); + pipe.println(framecnt001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(framecnt001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + framecnt001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(framecnt001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + framecnt001.QUIT + ")"); + log.display("Debugee FAILED"); + return framecnt001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return framecnt001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + int frames = 0; + + TestedClass(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display("Tested thread started"); + + // make remaining frames already having one + frames = 1; + makeFrames(FRAMES_COUNT - frames); + } + + // recursive make thread frames and notify debuggee + public void makeFrames(int count) { + frames++; + count--; + int local = frames + count; + if (count > 0) { + makeFrames(count); + } else { + log.display("Thread frames made: " + frames); + + // notify debuggee that thread ready for testing + synchronized (threadReady) { + threadReady.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Frames; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Frames. + * + * See frames001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class frames001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Frames"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "frames001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Frames"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Frames; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = frames001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = frames001a.THREAD_NAME; + + // names of the methods with frames + static final String TESTED_METHOD_NAME = frames001a.METHOD_NAME; + static final String RUN_METHOD_NAME = "run"; + + // expected number of frames count + static final int START_FRAME_INDEX = 2; + static final int FRAMES_COUNT = frames001a.FRAMES_COUNT - START_FRAME_INDEX; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new frames001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for methodID of the recursive method + log.display("Getting methodID by name: " + TESTED_METHOD_NAME); + long methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); + log.display(" got methodID: " + methodID); + + // query debuggee for methodID of the run() method + log.display("Getting methodID by name: " + RUN_METHOD_NAME); + long runMethodID = debugee.getMethodID(classID, RUN_METHOD_NAME, true); + log.display(" got methodID: " + runMethodID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // suspend tested thread into debyggee + log.display("Suspending thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + log.display(" thread suspended"); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID, methodID, runMethodID, classID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID, long methodID, long runMethodID, long classID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" startFrame: " + START_FRAME_INDEX); + command.addInt(START_FRAME_INDEX); + log.display(" length: " + FRAMES_COUNT); + command.addInt(FRAMES_COUNT); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract number of frames + int frames = 0; + try { + frames = reply.getInt(); + log.display(" frames: " + frames); + } catch (BoundException e) { + log.complain("Unable to extract number of frames from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that frames count is not negative + if (frames < 0) { + log.complain("Negative value of frames count in reply packet: " + + frames); + success = false; + } + + // check that thread has an expected state + if (frames != FRAMES_COUNT) { + log.complain("Unexpected number of frames returned: " + + frames + " (expected: " + FRAMES_COUNT + ")"); + success = false; + } + + // use methodID of the recursive method to check all frames except the last one + long checkedMethodID = methodID; + + // extarct frame IDs and locations + for (int i = 0; i < frames; i++) { + + log.display(" frame #" + i + ":"); + + // extract frame ID + long frameID = 0; + try { + frameID = reply.getFrameID(); + log.display(" frameID: " + frameID); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " frameID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract frame location + JDWP.Location location = null; + try { + location = reply.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + e.printStackTrace(log.getOutStream()); + log.complain("Unable to extract " + i + " frame location from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that frameID is not negative integer + if (frameID < 0) { + log.complain("Negative value of " + i + " frameID: " + + frameID); + success = false; + } + + // check that type tag of location is CLASS tag + if (location.getTag() != JDWP.TypeTag.CLASS) { + log.complain("Unexpected type tag of " + i + " frame location: " + + location.getTag() + "(expected: " + JDWP.TypeTag.CLASS + ")"); + success = false; + } + + // check that classID of location is equal to original classID + if (location.getClassID() != classID) { + log.complain("Unexpected classID of " + i + " frame location: " + + location.getClassID() + "(expected: " + classID + ")"); + success = false; + } + + // use methodID of run() method for checking last frame + if (i == frames - 1) { + checkedMethodID = runMethodID; + } + + // check that methodID of location is equal to one of original methodIDs + if (location.getMethodID() != checkedMethodID) { + log.complain("Unexpected methodID of " + i + " frame location: " + + location.getMethodID() + "(expected: " + checkedMethodID + ")"); + success = false; + } + + // check that code index of location is not negative integer + if (location.getIndex() < 0) { + log.complain("Negative value of index of " + i + " frame location: " + + location.getIndex()); + success = false; + } + + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Frames/frames001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Frames + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks the following assertions: + * 1. Number of returned frames is the same as requested + * 2. Location of each frame belongs to the tested class + * 3. Location of the last frame belongs to the method run() + * 4. Locations of all other frames belogs to the method makeFrames() + * 5. Each frameID is a not negative integer value. + * Test consists of two compoments: + * debugger: frames001 + * debuggee: frames001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Also debugger + * suspends the thread before sending the tested command. + * Then, debugger creates command packet for ThreadReference.Frames + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of frames in the thread. Also test checks above + * mentioned assertions. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Frames.frames001 + * nsk.jdwp.ThreadReference.Frames.frames001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Frames.frames001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Frames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class frames001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + public static final String METHOD_NAME = "makeFrames"; + + // frames count for tested thread in recursive method invokation + public static final int FRAMES_COUNT = 10; + + // notification object to notify debuggee that thread is ready + private static Object threadReady = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + frames001a _frames001a = new frames001a(); + System.exit(frames001.JCK_STATUS_BASE + _frames001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadReady) { + TestedClass.thread.start(); + try { + threadReady.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + frames001.READY); + pipe.println(frames001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(frames001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + frames001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(frames001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + frames001.QUIT + ")"); + log.display("Debugee FAILED"); + return frames001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return frames001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + int frames = 0; + + TestedClass(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display("Tested thread started"); + + // make remaining frames already having one + frames = 1; + makeFrames(FRAMES_COUNT - frames); + + } + + // recursive make thread frames and notify debuggee + public void makeFrames(int count) { + frames++; + count--; + int local = frames + count; + if (count > 0) { + makeFrames(count); + } else { + log.display("Thread frames made: " + frames); + + // notify debuggee that thread ready for testing + synchronized (threadReady) { + threadReady.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + + } + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Interrupt; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Interrupt. + * + * See interrupt001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class interrupt001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String RUN = "run"; + static final String INTERRUPTED_TRUE = "interrupted/true"; + static final String INTERRUPTED_FALSE = "interrupted/false"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Interrupt"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "interrupt001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Interrupt"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Interrupt; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = interrupt001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = interrupt001a.THREAD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new interrupt001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + log.display("\n>>> Checking that tested thread was really interrupted \n"); + + // check if the thread was really interrupted + confirmThreadInterrupted(); + + } finally { + log.display("\n>>> Finishing test \n"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // there are no data to extract + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + + /** + * Wait for signal from debugee that thread was really interrupted + */ + void confirmThreadInterrupted() { + + // send debugee signal to run + log.display("Sending signal to debugee: " + RUN); + pipe.println(RUN); + + // wait for signal DONE from debuggee + log.display("Waiting for signal from debugee: " + INTERRUPTED_TRUE); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + // check received signal + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + INTERRUPTED_TRUE + ")"); + } else if (signal.equals(INTERRUPTED_TRUE)) { + log.display("Tested thread was interrupted into debuggee"); + } else if (signal.equals(INTERRUPTED_FALSE)) { + log.complain("Tested thread was NOT interrupted into debuggee"); + success = false; + } else { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + INTERRUPTED_TRUE + ")"); + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Interrupt/interrupt001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Interrupt + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks following assertions: + * 1. Tested thread is really interrupted into debuggee VM. + * 2. Thread.isInterrupted() for the thread returns true. + * Test consists of two compoments: + * debugger: interrupt001 + * debuggee: interrupt001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. The tested thread + * into debuggee is in a waiting state in this time and is ready for + * interruption. + * Then, debugger creates command packet for ThreadReference.Interrupt + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and ensures the packet does not has any data. Then debugger requests + * from debuggee confirmation about thread interruption and checkes + * above mentioned assertions. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * Modified due to fix of: + * 4759463 TEST_BUG: tests against ThreadReference.interrupt() should be corrected + * Test fixed due to test bug: + * 4960198 TEST_BUG: race in nsk/jdwp/ThreadReference/Interrupt/interrupt001 + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Interrupt.interrupt001 + * nsk.jdwp.ThreadReference.Interrupt.interrupt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Interrupt.interrupt001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Interrupt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class interrupt001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + public static volatile boolean interrupted = false; + + // notification object to notify debuggee that thread is started + private static Object threadStarting = new Object(); + // object which thread will wait for before being interruted + private static Object threadWaiting = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + interrupt001a _interrupt001a = new interrupt001a(); + System.exit(interrupt001.JCK_STATUS_BASE + _interrupt001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarting) { + TestedClass.thread.start(); + try { + threadStarting.wait(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started:\n\t" + e); + pipe.println(interrupt001.ERROR); + log.display("Debugee FAILED"); + return interrupt001.FAILED; + } + + // send debugger signal READY + log.display("Sending signal to debugger: " + interrupt001.READY); + pipe.println(interrupt001.READY); + } + + // wait for signal RUN from debugeer + log.display("Waiting for signal from debugger: " + interrupt001.RUN); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(interrupt001.RUN)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + interrupt001.RUN + ")"); + log.display("Debugee FAILED"); + return interrupt001.FAILED; + } + + // wait for thread finished in a waittime interval + if (TestedClass.thread.isAlive()) { + log.display("Waiting for tested thread finished for timeout: " + timeout); + try { + TestedClass.thread.join(timeout); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished:\n\t" + e); + pipe.println(interrupt001.ERROR); + log.display("Debugee FAILED"); + return interrupt001.FAILED; + } + } + + // test if thread was interrupted by debugger + if (interrupt001a.interrupted) { + log.display("Sending signal to debugger: " + interrupt001.INTERRUPTED_TRUE); + pipe.println(interrupt001.INTERRUPTED_TRUE); + } else { + log.display("Sending signal to debugger: " + interrupt001.INTERRUPTED_FALSE); + pipe.println(interrupt001.INTERRUPTED_FALSE); + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + interrupt001.QUIT); + signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(interrupt001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + interrupt001.QUIT + ")"); + log.display("Debugee FAILED"); + return interrupt001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return interrupt001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + TestedClass(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display("Tested thread started"); + + synchronized (threadWaiting) { + + // notify debuggee that thread started + synchronized (threadStarting) { + threadStarting.notifyAll(); + } + + // wait infinitely for notification object + try { + threadWaiting.wait(); + log.complain("Tested thread NOT interrupted"); + } catch (InterruptedException e) { + log.display("Tested thread interrupted"); + interrupt001a.interrupted = true; + } + } + + log.display("Tested thread finished"); + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Name; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Name. + * + * See name001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class name001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Name"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "name001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Name"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Name; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = name001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = name001a.THREAD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new name001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + long threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract thread name + String threadName = null; + try { + threadName = reply.getString(); + log.display(" threadName: " + threadName); + } catch (BoundException e) { + log.complain("Unable to extract thread name from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that thread name is equal to the expected one + if (!threadName.equals(TESTED_THREAD_NAME)) { + log.complain("Unexpected thread name returned in the reply packet: " + + threadName + " (expected: " + TESTED_THREAD_NAME + ")"); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Name/name001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Name + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned name of the tested thread is equal to the expected one. + * Test consists of two compoments: + * debugger: name001 + * debuggee: name001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. + * Then, debugger creates command packet for ThreadReference.Name + * command with the found threadID as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts thread name. Also test checks that the name is equal + * to the expected one. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Name.name001 + * nsk.jdwp.ThreadReference.Name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Name.name001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class name001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + // notification object to notify debuggee that thread started + private static Object threadStarted = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + name001a _name001a = new name001a(); + System.exit(name001.JCK_STATUS_BASE + _name001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarted) { + TestedClass.thread.start(); + try { + threadStarted.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + name001.READY); + pipe.println(name001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(name001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + name001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(name001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + name001.QUIT + ")"); + log.display("Debugee FAILED"); + return name001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return name001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // notify debuggee that thread really started + synchronized (threadStarted) { + threadStarted.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.OwnedMonitors; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.OwnedMonitors. + * + * See ownmonitors001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class ownmonitors001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.OwnedMonitors"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "ownmonitors001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_GET_OWNED_MONITOR_INFO; + static final String VM_CAPABILITY_NAME = "canGetOwnedMonitorInfo"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.OwnedMonitors"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.OwnedMonitors; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_THREAD_NAME = ownmonitors001a.THREAD_NAME; + static final String THREAD_FIELD_NAME = ownmonitors001a.THREAD_FIELD_NAME; + static final String OWNED_MONITOR_FIELD_NAME = + ownmonitors001a.OWNED_MONITOR_FIELD_NAME; + static final String NOT_OWNED_MONITOR_FIELD_NAME = + ownmonitors001a.NOT_OWNED_MONITOR_FIELD_NAME; + + // expected number of owned monitors + static final int OWNED_MONITORS = 1; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new ownmonitors001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + long threadID = 0; + try { + log.display("\n>>> Checking VM capability \n"); + + // check for VM capability + log.display("Checking VM capability: " + VM_CAPABILITY_NAME); + if (!debugee.getCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME)) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + THREAD_FIELD_NAME); + threadID = queryObjectID(classID, THREAD_FIELD_NAME, JDWP.Tag.THREAD); + log.display(" got threadID: " + threadID); + + // query debuggee for objectID value for owned monitor from a static field + log.display("Getting objectID value for owned monitor from static field: " + + OWNED_MONITOR_FIELD_NAME); + long ownedMonitorID = queryObjectID(classID, + OWNED_MONITOR_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + ownedMonitorID); + + // query debuggee for objectID value for not owned monitor from a static field + log.display("Getting objectID value for not owned monitor from static field: " + + NOT_OWNED_MONITOR_FIELD_NAME); + long notOwnedMonitorID = queryObjectID(classID, + NOT_OWNED_MONITOR_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + notOwnedMonitorID); + + // suspend tested thread into debyggee + log.display("Suspending thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + log.display(" thread suspended"); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID, ownedMonitorID, notOwnedMonitorID); + + } finally { + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value of static class field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + + "\": " + value.getTag() + " (expected: " + tag + ")"); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID, long expectedObjectID, long unexpectedObjectID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract number of frames + int owned = 0; + try { + owned = reply.getInt(); + log.display(" owned: " + owned); + } catch (BoundException e) { + log.complain("Unable to extract number of owned minitors from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that frames count is not negative + if (owned < 0) { + log.complain("Negative number of owned monitors in reply packet: " + + owned); + success = false; + } + + // check that thread has an expected state + if (owned != OWNED_MONITORS) { + log.complain("Unexpected number of owned monitors returned: " + + owned + " (expected: " + OWNED_MONITORS + ")"); + success = false; + } + + boolean foundExpected = false; + + // extract objectID's for owned monitors + for (int i = 0; i < owned; i++) { + + log.display(" monitor #" + i + ":"); + + // extract object tag + byte tag = (byte)0; + try { + tag = reply.getByte(); + log.display(" tag: " + tag); + } catch (BoundException e) { + log.complain("Unable to extract tag for monitor object from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract objectID + long objectID = 0; + try { + objectID = reply.getObjectID(); + log.display(" objectID: " + objectID); + } catch (BoundException e) { + log.complain("Unable to extract " + i + " monitor objectID from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that tag is an OBJECT tag + if (tag != JDWP.Tag.OBJECT) { + log.complain("Unexpected tag for monitor object received:" + tag + + " (expected" + JDWP.Tag.OBJECT); + success = false; + } + + // check that objectID is not negative integer + if (objectID < 0) { + log.complain("Negative value of " + i + " objectID received: " + + objectID); + success = false; + } + + // check that expected objectID is in the list + if (objectID == expectedObjectID) { + log.display("Found expected monitor objectID: " + expectedObjectID); + foundExpected = true; + } + + // check that not expected objectID is in the list + if (objectID == unexpectedObjectID) { + log.complain("Unexpected objectID found in the list of owned monitors: " + + unexpectedObjectID); + success = false; + } + + } + + // check if expected owned monitor objectID not found + if (!foundExpected) { + log.complain("Expected objectID not found in the list of owned monitors: " + + expectedObjectID); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: OwnedMonitors + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Also test checks that only one owned monitor returned + * for the tested thread. + * Test consists of two compoments: + * debugger: ownmonitors001 + * debuggee: ownmonitors001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Also debugger + * suspends the thread before sending the tested command. The tested + * thread is owning only one object monitor at this moment. + * Then, debugger creates command packet for ThreadReference.OwnedMonitors + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts list ob objectIDs for thread owned monitors. Also test + * checks above mentioned assertions. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * For JDK 1.4.0-beta3 (build 1.4.0-beta3-b84) and earlier this test passed + * because target VM does not support VM capability: canGetOwnedMonitorInfo + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.OwnedMonitors.ownmonitors001 + * nsk.jdwp.ThreadReference.OwnedMonitors.ownmonitors001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.OwnedMonitors.ownmonitors001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.OwnedMonitors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class ownmonitors001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String THREAD_FIELD_NAME = "thread"; + public static final String OWNED_MONITOR_FIELD_NAME = "ownedMonitor"; + public static final String NOT_OWNED_MONITOR_FIELD_NAME = "notOwnedMonitor"; + + // notification object to notify debuggee that thread is ready + private static Object threadReady = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + ownmonitors001a _ownmonitors001a = new ownmonitors001a(); + System.exit(ownmonitors001.JCK_STATUS_BASE + _ownmonitors001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadReady) { + TestedClass.thread.start(); + try { + threadReady.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + ownmonitors001.READY); + pipe.println(ownmonitors001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(ownmonitors001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + ownmonitors001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(ownmonitors001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + ownmonitors001.QUIT + ")"); + log.display("Debugee FAILED"); + return ownmonitors001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return ownmonitors001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + // field with object whose monitor the tested thread owns + public static Object ownedMonitor = new Object(); + + // field with object whose monitor the tested thread does not own + public static Object notOwnedMonitor = new Object(); + + TestedClass(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display("Tested thread started"); + + // get ownership for the tested monitors + synchronized (ownedMonitor) { + + // notify debuggee that thread ready for testing + synchronized (threadReady) { + threadReady.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + + } + + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: OwnedMonitorsStackDepthInfo + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: ownedMonitorsStackDepthInfo001 + * debuggee: ownedMonitorsStackDepthInfo001a + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Debuggee during startup start test thread which acquires 6 different monitors in following ways: + * - entering synchronized method + * - entering synchronized method for thread object itself + * - entering synchronized static method + * - entering synchronized method for thread class itself + * - entering synchronized block on non-static object + * - acquire JNI monitor through JNI MonitorEnter() + * Debuggee save information about acquired monitors(monitor instance and stack depth location + * where monitor was acquired) in static fields with names monitor1, ..., monitor6 and depth1, ..., depth6 to + * simplify access to this information for debugger. + * Debugger obtains threadID for test thread. + * Debugger creates command packet for OwnedMonitorsStackDepthInfo command with the + * found threadID as an argument, writes packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure and extract + * monitors ids and stack depth locations. + * Debugger obtains information about acquired monitors from debuggee's static fields monitor1, ..., monitor6 and + * depth1, ..., depth6 and checks that this data and data received via JDWP command are identical. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo001.ownedMonitorsStackDepthInfo001 + * @run main/othervm/native/timeout=420 PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo001.ownedMonitorsStackDepthInfo001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo001; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; + +public class ownedMonitorsStackDepthInfo001 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo001.ownedMonitorsStackDepthInfo001a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsStackDepthInfo001().runIt(argv, out); + } + + // information for acquired monitor + static class MonitorInfo { + long monitorObjectID; + + int depth; + + public MonitorInfo(long monitorObjectID, int depth) { + this.monitorObjectID = monitorObjectID; + this.depth = depth; + } + } + + private void testCommand() { + try { + int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.OwnedMonitorsStackDepthInfo; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + + long threadID = debuggee.getThreadID(ownedMonitorsStackDepthInfo001a.lockingThreadName); + log.display("threadID = " + threadID); + + debuggee.suspendThread(threadID); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command); + + MonitorInfo expectedMonitors[] = new MonitorInfo[ownedMonitorsStackDepthInfo001a.expectedMonitorCounts]; + + long classID = debuggee.getReferenceTypeID(createTypeSignature(getDebugeeClassName())); + + // obtain information about aquired monitors + for (int i = 0; i < ownedMonitorsStackDepthInfo001a.expectedMonitorCounts; i++) { + long monitorID = queryObjectID(classID, "monitor" + (i + 1)); + int depth = ((Integer) debuggee.getStaticFieldValue(classID, "depth" + (i + 1), JDWP.Tag.INT).getValue()).intValue(); + + expectedMonitors[i] = new MonitorInfo(monitorID, depth); + } + + int owned = reply.getInt(); + + log.display("owned = " + owned); + + // check that correct value of 'owned' was received + if (owned != expectedMonitors.length) { + setSuccess(false); + log.complain("Unexpected value of 'owned': " + owned + ", expected value is " + expectedMonitors.length); + } + + MonitorInfo receivedMonitors[] = new MonitorInfo[owned]; + + for (int i = 0; i < owned; i++) { + JDWP.Value value = reply.getValue(); + log.display("tagged-ObjectID = " + value); + + int stack_depth = reply.getInt(); + log.display("stack_depth = " + stack_depth); + + receivedMonitors[i] = new MonitorInfo(((Long) value.getValue()).longValue(), stack_depth); + } + + // check that correct information about acquired monitors was received + for (int i = 0; i < owned; i++) { + boolean monitorFound = false; + + for (int j = 0; j < expectedMonitors.length; j++) { + if (receivedMonitors[i].monitorObjectID == expectedMonitors[j].monitorObjectID) { + monitorFound = true; + + if (receivedMonitors[i].depth != expectedMonitors[j].depth) { + setSuccess(false); + log.complain("Unexpected monitor depth for monitor " + receivedMonitors[i].monitorObjectID + ": " + + receivedMonitors[i].depth + ", expected value is " + expectedMonitors[j].depth); + } + + break; + } + } + + if (!monitorFound) { + setSuccess(false); + log.complain("Unexpected monitor: monitor" + receivedMonitors[i].monitorObjectID + " stack_depth" + receivedMonitors[i].depth); + } + } + + if (!getSuccess()) { + log.complain("Expected monitors: "); + for (int i = 0; i < expectedMonitors.length; i++) { + log.complain("monitor: " + expectedMonitors[i].monitorObjectID + " " + expectedMonitors[i].depth); + } + } + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + testCommand(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo001; + +import java.util.*; +import nsk.share.TestBug; +import nsk.share.jdwp.*; +import nsk.share.locks.LockingThread; + +public class ownedMonitorsStackDepthInfo001a extends AbstractJDWPDebuggee { + public static Object monitor1; + + public static int depth1; + + public static Object monitor2; + + public static int depth2; + + public static Object monitor3; + + public static int depth3; + + public static Object monitor4; + + public static int depth4; + + public static Object monitor5; + + public static int depth5; + + public static Object monitor6; + + public static int depth6; + + public static int expectedMonitorCounts = 6; + + public static String lockingThreadName = "LockingThread"; + + public static LockingThread lockingThread; + + protected void init(String args[]) { + super.init(args); + + List locksTypes = new ArrayList(); + + // LockingThread acquire 6 different monitors + locksTypes.add(LockingThread.SYNCHRONIZED_METHOD); + locksTypes.add(LockingThread.JNI_MONITOR_ENTER); + locksTypes.add(LockingThread.SYNCHRONIZED_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_STATIC_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK); + locksTypes.add(LockingThread.SYNCHRONIZED_STATIC_METHOD); + + lockingThread = new LockingThread(log, locksTypes); + lockingThread.setName(lockingThreadName); + lockingThread.start(); + lockingThread.waitState(); + + // get information about acquired monitors and save it in static fields to simplify + // access to this information for debugger + LockingThread.DebugMonitorInfo monitorsInfo[] = lockingThread.getMonitorsInfo(true); + + if (monitorsInfo.length != 6) { + throw new TestBug("Locking thread return invalid monitors count: " + monitorsInfo.length + ", expected value is " + 6); + } + + monitor1 = monitorsInfo[0].monitor; + depth1 = monitorsInfo[0].stackDepth; + + monitor2 = monitorsInfo[1].monitor; + depth2 = monitorsInfo[1].stackDepth; + + monitor3 = monitorsInfo[2].monitor; + depth3 = monitorsInfo[2].stackDepth; + + monitor4 = monitorsInfo[3].monitor; + depth4 = monitorsInfo[3].stackDepth; + + monitor5 = monitorsInfo[4].monitor; + depth5 = monitorsInfo[4].stackDepth; + + monitor6 = monitorsInfo[5].monitor; + depth6 = monitorsInfo[5].stackDepth; + } + + public static void main(String args[]) { + new ownedMonitorsStackDepthInfo001a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: OwnedMonitorsStackDepthInfo + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: ownedMonitorsStackDepthInfo002 + * debuggee: nsk.share.jdwp.TestDebuggeeType2 + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Test performs checks for cases when incorrect data is sent in command. + * Following cases are tested: + * - create command with -1 as threadID, expect INVALID_OBJECT error + * - create command with referenceID instead of threadID, expect INVALID_THREAD error + * - try execute command for thread wich has finished execution, expect INVALID_THREAD error + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo002.ownedMonitorsStackDepthInfo002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo002.ownedMonitorsStackDepthInfo002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo002; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; +import nsk.share.jpda.AbstractDebuggeeTest; +import nsk.share.jpda.StateTestThread; + +public class ownedMonitorsStackDepthInfo002 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return AbstractJDWPDebuggee.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsStackDepthInfo002().runIt(argv, out); + } + + private void sendCommand(long threadID, boolean trySuspend, int errorCode) { + try { + int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.OwnedMonitorsStackDepthInfo; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("threadID = " + threadID); + + // suspend thread or not (can't use suspending when create command with invalid threadID) + if (trySuspend) + debuggee.suspendThread(threadID); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + // in this test always expect reply with error + getReply(command, true, errorCode); + + return; + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + // create command with threadID = -1, expect INVALID_OBJECT error + sendCommand(-1, false, JDWP.Error.INVALID_OBJECT); + + // create command with referenceTypeID instead of trheadID, expect INVALID_THREAD error + sendCommand(debuggee.getReferenceTypeID(createTypeSignature(getDebugeeClassName())), false, JDWP.Error.INVALID_THREAD); + + // create StateTestThread and force this finish execution + pipe.println(AbstractDebuggeeTest.COMMAND_CREATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + // skip one state(thread not running), because of can obtain threadID only for running thread + pipe.println(AbstractDebuggeeTest.COMMAND_NEXTSTATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + long threadID = debuggee.getThreadID(AbstractDebuggeeTest.stateTestThreadName); + + int state = 2; + + // skip all states + while (state++ < StateTestThread.stateTestThreadStates.length) { + pipe.println(AbstractDebuggeeTest.COMMAND_NEXTSTATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + } + + // send command for thread which has exited expect INVALID_THREAD error + sendCommand(threadID, true, JDWP.Error.INVALID_THREAD); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Resume; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Resume. + * + * See resume001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class resume001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Resume"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "resume001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Resume"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Resume; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = resume001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = resume001a.THREAD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new resume001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + long threadID = 0; + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // request debuggee to suspend tested thread + log.display("Suspendig thread into debuggee for threadID: " + threadID); + debugee.suspendThread(threadID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + } finally { + + log.display("\n>>> Finishing test \n"); + + // resume suspended thread + if (threadID != 0) { + log.display("Resuming potentially suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Query debuggee for suspend status of the thread. + */ + int querySuspendStatus(long threadID) { + log.display("Getting suspend status for threadID: " + threadID); + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Status); + command.addObjectID(threadID); + ReplyPacket reply = debugee.receiveReplyFor(command); + + try { + reply.resetPosition(); + + int threadStatus = reply.getInt(); + int suspendStatus = reply.getInt(); + log.display(" got suspendStatus: " + suspendStatusString(suspendStatus)); + return suspendStatus; + } catch (BoundException e) { + throw new Failure("Caught BoundException while parsing reply for ThreadReference.Status:\n\t" + + e); + } + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // check that tested thread is not suspended before command sent + int suspendStatus = querySuspendStatus(threadID); + if (suspendStatus != JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) { + throw new Failure("SuspendStatus reports thread is not suspended before sending Resume command: " + + suspendStatusString(suspendStatus)); + } else { + log.display("Thread is suspended"); + } + + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that tested thread is suspended after Resume command sent + suspendStatus = querySuspendStatus(threadID); + if ((suspendStatus & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) != 0) { + log.complain("SuspendStatus reports thread is suspended after Resume command sent: " + + suspendStatusString(suspendStatus)); + } else { + log.display("Thread is not suspended"); + } + + } + + /** + * Return string representation of thread suspend status. + */ + private static String suspendStatusString(int status) { + String s = null; + if ((status & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) != 0) { + s = "SUSPEND_STATUS_SUSPENDED"; + } else if (status == 0) { + s = "NONE"; + } else { + s = "unknown"; + } + return status + "=" + s; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Resume/resume001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Resume + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * thread becomes "not suspended" status after the command. + * Test consists of two compoments: + * debugger: resume001 + * debuggee: resume001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Debugger suspends + * the thread and checks that the thread has "suspended" status before + * sending the tested command. + * Then, debugger creates command packet for ThreadReference.Resume + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and ensures there is no data into the package. Also debugger queries + * debuggee for suspend status of the tested thread and chacks that thread + * has status "not suspended". + * Finally, debugger resumes suspended thread into debuggee, sends debuggee + * signal to quit, waits for it exits and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Resume.resume001 + * nsk.jdwp.ThreadReference.Resume.resume001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Resume.resume001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class resume001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + // notification object to notify debuggee that thread started + private static Object threadStarted = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + resume001a _resume001a = new resume001a(); + System.exit(resume001.JCK_STATUS_BASE + _resume001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarted) { + TestedClass.thread.start(); + try { + threadStarted.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + resume001.READY); + pipe.println(resume001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(resume001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + resume001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(resume001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + resume001.QUIT + ")"); + log.display("Debugee FAILED"); + return resume001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return resume001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // notify debuggee that thread really started + synchronized (threadStarted) { + threadStarted.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Status; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Status. + * + * See status001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class status001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Status"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "status001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Status"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Status; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = status001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = status001a.THREAD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new status001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + long threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // extract thread status + int threadStatus = 0; + try { + threadStatus = reply.getInt(); + log.display(" threadStatus: " + threadStatusString(threadStatus)); + } catch (BoundException e) { + log.complain("Unable to extract thread status from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // extract suspend status + int suspendStatus = 0; + try { + suspendStatus = reply.getInt(); + log.display(" suspendStatus: " + suspendStatusString(suspendStatus)); + } catch (BoundException e) { + log.complain("Unable to extract thread status from reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check that both status code are not negative values + if (threadStatus < 0) { + log.complain("Negative value of thread status in reply packet: " + + threadStatusString(threadStatus)); + success = false; + } + if (suspendStatus < 0) { + log.complain("Negative value of suspend status in reply packet: " + + suspendStatusString(suspendStatus)); + success = false; + } + + // check that thread has an expected state + if (!(threadStatus == JDWP.ThreadStatus.RUNNING + || threadStatus == JDWP.ThreadStatus.MONITOR)) { + log.complain("Unexpected thread status returned in the reply packet: " + + threadStatusString(threadStatus) + + " (expected: " + threadStatusString(JDWP.ThreadStatus.RUNNING) + + " or " + threadStatusString(JDWP.ThreadStatus.MONITOR) + ")"); + success = false; + } + + // check that thread was not suspended + if ((suspendStatus & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) != 0) { + log.complain("Unexpected suspend status returned in the reply packet: " + + threadStatusString(threadStatus) + + " (expected: " + "not suspended" + ")"); + success = false; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + + /** + * Return string representation of thread status code. + */ + private static String threadStatusString(int status) { + String s = null; + switch (status) { + case JDWP.ThreadStatus.MONITOR: + s = "MONITOR"; + break; + case JDWP.ThreadStatus.RUNNING: + s = "RUNNING"; + break; + case JDWP.ThreadStatus.SLEEPING: + s = "SLEEPING"; + break; + case JDWP.ThreadStatus.WAIT: + s = "WAIT"; + break; + case JDWP.ThreadStatus.ZOMBIE: + s = "ZOMBIE"; + break; + default: + s = "unknown"; + break; + } + return status + "=" + s; + } + + /** + * Return string representation of thread suspend status. + */ + private static String suspendStatusString(int status) { + String s = null; + if ((status & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) != 0) { + s = "SUSPEND_STATUS_SUSPENDED"; + } else if (status == 0) { + s = "NONE"; + } else { + s = "unknown"; + } + return status + "=" + s; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Status/status001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Status + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned thread status and suspend status have expected values. + * Test consists of two compoments: + * debugger: status001 + * debuggee: status001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. + * Then, debugger creates command packet for ThreadReference.Status + * command with the found threadID as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts thread name. Also test checks that thread status and + * suspend status have expected values. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Status.status001 + * nsk.jdwp.ThreadReference.Status.status001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Status.status001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Status; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class status001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + // notification object to notify debuggee that thread started + private static Object threadStarted = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + status001a _status001a = new status001a(); + System.exit(status001.JCK_STATUS_BASE + _status001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarted) { + TestedClass.thread.start(); + try { + threadStarted.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + status001.READY); + pipe.println(status001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(status001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + status001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(status001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + status001.QUIT + ")"); + log.display("Debugee FAILED"); + return status001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return status001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // notify debuggee that thread really started + synchronized (threadStarted) { + threadStarted.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Stop; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Stop. + * + * See stop001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class stop001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String RUN = "run"; + static final String STOPPED = "stopped"; + static final String NOT_STOPPED = "not_stopped"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Stop"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "stop001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Stop"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Stop; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_THREAD_NAME = stop001a.THREAD_NAME; + static final String THREAD_FIELD_NAME = stop001a.THREAD_FIELD_NAME; + static final String THROWABLE_FIELD_NAME = stop001a.THROWABLE_FIELD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new stop001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + THREAD_FIELD_NAME); + long threadID = queryObjectID(classID, THREAD_FIELD_NAME, JDWP.Tag.THREAD); + log.display(" got threadID: " + threadID); + + // query debuggee for throwable objectID value from a static field + log.display("Getting throwable objectID value from static field: " + + THROWABLE_FIELD_NAME); + long objectID = queryObjectID(classID, THROWABLE_FIELD_NAME, JDWP.Tag.OBJECT); + log.display(" got objectID: " + objectID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID, objectID); + + log.display("\n>>> Checking that tested thread was really stopped \n"); + + // check if the thread was really stopped + confirmThreadStopped(); + + } finally { + log.display("\n>>> Finishing test \n"); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for objectID value from the class static field. + */ + long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != tag) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long objectID = ((Long)value.getValue()).longValue(); + return objectID; + } + + /** + * Perform testing JDWP command for specified threadID and throwable objectID. + */ + void testCommand(long threadID, long objectID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + log.display(" throwable: " + objectID); + command.addObjectID(objectID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // there are no data to extract + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + } + + /** + * Wait for signal from debugee that thread was really stopped + */ + void confirmThreadStopped() { + + // send debugee signal to run + log.display("Sending signal to debugee: " + RUN); + pipe.println(RUN); + + // wait for signal DONE from debuggee + log.display("Waiting for signal from debugee: " + STOPPED); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + // check received signal + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + STOPPED + ")"); + } else if (signal.equals(STOPPED)) { + log.display("Tested thread was really stopped into debuggee"); + } else if (signal.equals(NOT_STOPPED)) { + log.complain("Tested thread was NOT really stopped into debuggee"); + success = false; + } else { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + STOPPED + ")"); + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Stop/stop001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Stop + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * the thread is really stopped into debuggee VM. + * Test consists of two compoments: + * debugger: stop001 + * debuggee: stop001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. The tested thread + * into debuggee is in a waiting state in this time and is ready for + * stopping. + * Then, debugger creates command packet for ThreadReference.Stop + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and ensures the packet does not has any data. Then debugger requests + * from debuggee confirmation about thread stopped and checks above + * mentioned assertions. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Stop.stop001 + * nsk.jdwp.ThreadReference.Stop.stop001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Stop.stop001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Stop; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class stop001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String THREAD_FIELD_NAME = "thread"; + public static final String THROWABLE_FIELD_NAME = "throwable"; + + // frames count for tested thread in recursive method invokation + public static final int FRAMES_COUNT = 10; + + // notification object to notify debuggee that thread is started + private static Object threadStarting = new Object(); + // object which thread will wait for before being interruted + private static Object threadWaiting = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + stop001a _stop001a = new stop001a(); + System.exit(stop001.JCK_STATUS_BASE + _stop001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarting) { + TestedClass.thread.start(); + try { + threadStarting.wait(); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started:\n\t" + e); + pipe.println(stop001.ERROR); + log.display("Debugee FAILED"); + return stop001.FAILED; + } + + // ensure that tested thread is waiting for object + synchronized (threadWaiting) { + // send debugger signal READY + log.display("Sending signal to debugger: " + stop001.READY); + pipe.println(stop001.READY); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + stop001.RUN); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(stop001.RUN)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + stop001.RUN + ")"); + log.display("Debugee FAILED"); + return stop001.FAILED; + } + + // wait for thread finished in a waittime interval + log.display("Waiting for tested thread finished for timeout: " + timeout); + try { + TestedClass.thread.join(timeout); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for tested thread finished:\n\t" + e); + pipe.println(stop001.ERROR); + log.display("Debugee FAILED"); + return stop001.FAILED; + } + + // test if thread was interrupted by debugger + if (TestedClass.thread.isAlive()) { + log.display("Sending signal to debugger: " + stop001.NOT_STOPPED); + pipe.println(stop001.NOT_STOPPED); + // interrupt thread to allow it to finish + TestedClass.thread.interrupt(); + } else { + log.display("Sending signal to debugger: " + stop001.STOPPED); + pipe.println(stop001.STOPPED); + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + stop001.QUIT); + signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(stop001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + stop001.QUIT + ")"); + log.display("Debugee FAILED"); + return stop001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return stop001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + // field with the tested Throwable value + public static volatile Throwable throwable = new Throwable("Tested throwable"); + + TestedClass(String name) { + super(name); + } + + // start the thread and recursive invoke makeFrames() + public void run() { + log.display("Tested thread started"); + + synchronized (threadWaiting) { + + // notify debuggee that thread started + synchronized (threadStarting) { + threadStarting.notifyAll(); + } + + // wait infinitely for notification object + try { + threadWaiting.wait(); + log.complain("Tested thread NOT interrupted"); + } catch (InterruptedException e) { + log.display("Tested thread interrupted"); + } + } + + log.display("Tested thread finished"); + } + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Suspend; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.Suspend. + * + * See suspend001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class suspend001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.Suspend"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "suspend001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.Suspend"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.Suspend; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = suspend001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = suspend001a.THREAD_NAME; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new suspend001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + long threadID = 0; + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + } finally { + + log.display("\n>>> Finishing test \n"); + + // resumme suspended thread + if (threadID != 0) { + log.display("Resuming suspended thread"); + debugee.resumeThread(threadID); + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Query debuggee for suspend status of the thread. + */ + int querySuspendStatus(long threadID) { + log.display("Getting suspend status for threadID: " + threadID); + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Status); + command.addObjectID(threadID); + ReplyPacket reply = debugee.receiveReplyFor(command); + + try { + reply.resetPosition(); + + int threadStatus = reply.getInt(); + int suspendStatus = reply.getInt(); + log.display(" got suspendStatus: " + suspendStatusString(suspendStatus)); + return suspendStatus; + } catch (BoundException e) { + throw new Failure("Caught BoundException while parsing reply for ThreadReference.Status:\n\t" + + e); + } + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // check that tested thread is not suspended before command sent + int suspendStatus = querySuspendStatus(threadID); + if (suspendStatus == JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) { + throw new Failure("SuspendStatus reports thread is suspended before sending Suspend command: " + + suspendStatusString(suspendStatus)); + } else { + log.display("Thread is not suspended"); + } + + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + // check that tested thread is suspended after Suspend command sent + suspendStatus = querySuspendStatus(threadID); + if ((suspendStatus & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) == 0) { + log.complain("SuspendStatus reports thread is not suspended after Suspend command sent: " + + suspendStatusString(suspendStatus)); + } else { + log.display("Thread is suspended"); + } + + } + + /** + * Return string representation of thread suspend status. + */ + private static String suspendStatusString(int status) { + String s = null; + if ((status & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) != 0) { + s = "SUSPEND_STATUS_SUSPENDED"; + } else if (status == 0) { + s = "NONE"; + } else { + s = "unknown"; + } + return status + "=" + s; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/Suspend/suspend001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: Suspend + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * thread becomes suspended status. + * Test consists of two compoments: + * debugger: suspend001 + * debuggee: suspend001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Debugger checks + * that thread has not suspended status before sending tested command. + * Then, debugger creates command packet for ThreadReference.Suspend + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and ensures there is no data into the package. Also debugger queries + * debuggee for suspend status of the tested thread and chacks that thread + * has status suspended. + * Finally, debugger resumes suspended thread into debuggee, sends debuggee + * signal to quit, waits for it exits and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.Suspend.suspend001 + * nsk.jdwp.ThreadReference.Suspend.suspend001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.Suspend.suspend001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.Suspend; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class suspend001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + // notification object to notify debuggee that thread started + private static Object threadStarted = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + suspend001a _suspend001a = new suspend001a(); + System.exit(suspend001.JCK_STATUS_BASE + _suspend001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarted) { + TestedClass.thread.start(); + try { + threadStarted.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + suspend001.READY); + pipe.println(suspend001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(suspend001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + suspend001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(suspend001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + suspend001.QUIT + ")"); + log.display("Debugee FAILED"); + return suspend001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return suspend001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // notify debuggee that thread really started + synchronized (threadStarted) { + threadStarted.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.SuspendCount; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: ThreadReference.SuspendCount. + * + * See suspendcnt001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class suspendcnt001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String ERROR = "error"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.SuspendCount"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "suspendcnt001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "ThreadReference.SuspendCount"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.SuspendCount; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of the tested thread and statioc field with thread value + static final String TESTED_CLASS_FIELD_NAME = suspendcnt001a.FIELD_NAME; + static final String TESTED_THREAD_NAME = suspendcnt001a.THREAD_NAME; + + // expected number od suspend count + static final int SUSPEND_COUNT = 5; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new suspendcnt001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + long threadID = 0; + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for threadID value from a static field + log.display("Getting threadID value from static field: " + + TESTED_CLASS_FIELD_NAME); + threadID = queryThreadID(classID, TESTED_CLASS_FIELD_NAME); + log.display(" got threadID: " + threadID); + + // request debuggee to suspend tested thread + log.display("Suspendig thread " + SUSPEND_COUNT + " times for threadID: " + threadID); + for (int i = 0; i < SUSPEND_COUNT; i++) { + debugee.suspendThread(threadID); + } + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(threadID); + + } finally { + + log.display("\n>>> Finishing test \n"); + + // resumme suspended thread + if (threadID != 0) { + log.display("Resuming " + SUSPEND_COUNT + " times suspended thread: " + threadID); + for (int i = 0; i < SUSPEND_COUNT; i++) { + debugee.resumeThread(threadID); + } + } + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (signal == null) { + throw new TestBug("Null signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } else if (signal.equals(ERROR)) { + throw new TestBug("Debugee was not able to start tested thread" + + " (received signal: " + signal + ")"); + } else if (!signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for threadID value of statuic field of the class. + */ + long queryThreadID(long classID, String fieldName) { + // get fieledID for static field (declared in the class) + long fieldID = debugee.getClassFieldID(classID, fieldName, true); + // get value of the field + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + + // check that value has THREAD tag + if (value.getTag() != JDWP.Tag.THREAD) { + throw new Failure("Not threadID value returned from debuggee: " + value); + } + + // extract threadID from the value + long threadID = ((Long)value.getValue()).longValue(); + return threadID; + } + + /** + * Query debuggee for suspend status of the thread. + */ + int querySuspendStatus(long threadID) { + log.display("Getting suspend status for threadID: " + threadID); + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Status); + command.addObjectID(threadID); + ReplyPacket reply = debugee.receiveReplyFor(command); + + try { + reply.resetPosition(); + + int threadStatus = reply.getInt(); + int suspendStatus = reply.getInt(); + log.display(" got suspendStatus: " + suspendStatusString(suspendStatus)); + return suspendStatus; + } catch (BoundException e) { + throw new Failure("Caught BoundException while parsing reply for ThreadReference.Status:\n\t" + + e); + } + } + + /** + * Perform testing JDWP command for specified threadID. + */ + void testCommand(long threadID) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" threadID: " + threadID); + command.addObjectID(threadID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int suspendCount = 0; + try { + suspendCount = reply.getInt(); + log.display(" suspendCount: " + suspendCount); + } catch (BoundException e) { + log.complain("Unable to extract suspend count number form the reply packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + if (suspendCount < 0) { + log.complain("Negative number of suspend count returned: " + suspendCount + + "(expected: " + SUSPEND_COUNT + ")"); + success = false; + } + + if (suspendCount != SUSPEND_COUNT) { + log.complain("Unexpected number of suspend count returned: " + suspendCount + + "(expected: " + SUSPEND_COUNT + ")"); + success = false; + } + + } + + /** + * Return string representation of thread suspend status. + */ + private static String suspendStatusString(int status) { + String s = null; + if ((status & JDWP.SuspendStatus.SUSPEND_STATUS_SUSPENDED) != 0) { + s = "SUSPEND_STATUS_SUSPENDED"; + } else if (status == 0) { + s = "NONE"; + } else { + s = "unknown"; + } + return status + "=" + s; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference + * command: SuspendCount + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned number of suspend count is equal to real number + * of thread suspending attempts. + * Test consists of two compoments: + * debugger: suspendcnt001 + * debuggee: suspendcnt001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains from debuggee classID for tested thread class + * and threadID as the value of a class static field. Debugger suspends + * the thread SUSPEND_COUNT times before sending the tested command. + * Then, debugger creates command packet for ThreadReference.SuspendCount + * command with the found threadID as an argument, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts number of suspend count. Also debugger checks that returned + * suspend count is not negative and equal to the expected SUSPEND_COUNT. + * Finally, debugger resumes suspended thread into debuggee, sends debuggee + * signal to quit, waits for it exits and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.SuspendCount.suspendcnt001 + * nsk.jdwp.ThreadReference.SuspendCount.suspendcnt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.SuspendCount.suspendcnt001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.SuspendCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class suspendcnt001a { + + // name for the tested thread + public static final String THREAD_NAME = "TestedThreadName"; + public static final String FIELD_NAME = "thread"; + + // notification object to notify debuggee that thread started + private static Object threadStarted = new Object(); + // lock object to prevent thread from exit + private static Object threadLock = new Object(); + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + private static volatile Log log = null; + + public static void main(String args[]) { + suspendcnt001a _suspendcnt001a = new suspendcnt001a(); + System.exit(suspendcnt001.JCK_STATUS_BASE + _suspendcnt001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // lock the object to prevent thread from exit + synchronized (threadLock) { + + // load tested class and create tested thread + log.display("Creating object of tested class"); + TestedClass.thread = new TestedClass(THREAD_NAME); + + // start the thread and wait for notification from it + synchronized (threadStarted) { + TestedClass.thread.start(); + try { + threadStarted.wait(); + // send debugger signal READY + log.display("Sending signal to debugger: " + suspendcnt001.READY); + pipe.println(suspendcnt001.READY); + } catch (InterruptedException e) { + log.complain("Interruption while waiting for thread started: " + e); + pipe.println(suspendcnt001.ERROR); + } + } + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + suspendcnt001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (signal == null || !signal.equals(suspendcnt001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + suspendcnt001.QUIT + ")"); + log.display("Debugee FAILED"); + return suspendcnt001.FAILED; + } + + // allow started thread to exit + } + + // exit debugee + log.display("Debugee PASSED"); + return suspendcnt001.PASSED; + } + + // tested thread class + public static class TestedClass extends Thread { + + // field with the tested Thread value + public static volatile TestedClass thread = null; + + TestedClass(String name) { + super(name); + } + + public void run() { + log.display("Tested thread started"); + + // notify debuggee that thread really started + synchronized (threadStarted) { + threadStarted.notifyAll(); + } + + // wait for lock object released + synchronized (threadLock) { + log.display("Tested thread finished"); + } + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.ThreadGroup; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class threadgroup001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.ThreadReference.ThreadGroup"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "threadgroup001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "ThreadReference.ThreadGroup"; + static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.ThreadGroup; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new threadgroup001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + + try { + + // get top level thread groups + + log.display("Getting IDs for top level thread groups"); + + long[] threadGroupIDs = null; + int groups = 0; + + { + log.display("Create command packet " + "TopLevelThreadGroups"); + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.TopLevelThreadGroups); + + log.display("Waiting for reply to command"); + ReplyPacket reply = debugee.receiveReplyFor(command); + log.display("Valid reply packet received"); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + groups = reply.getInt(); + log.display(" groups: " + groups); + + threadGroupIDs = new long[groups]; + + for (int i = 0; i < groups; i++) { + long threadGroupID = reply.getObjectID(); + log.display(" #" + i + " threadGroupID: " + threadGroupID); + threadGroupIDs[i] = threadGroupID; + } + + if (groups < 0) { + log.complain("Negative number of thread groups returned while getting top level thread groups IDs: " + groups); + success = false; + } + + if (groups == 0) { + log.complain("No thread groups IDs returned while getting top level thread groups IDs: " + groups); + success = false; + } + + } + + // get threads from all thread groups found + + boolean found = false; + long checkedThreadGroupID = 0; + + long[] threadIDs = null; + int threads = 0; + + for (int i = 0; i < groups; i++) { + checkedThreadGroupID = threadGroupIDs[i]; + log.display("Getting IDs of the thread from thread group: #" + i); + + log.display("Create command packet " + + "ThreadGroupReference.Children"); + CommandPacket command = new CommandPacket(JDWP.Command.ThreadGroupReference.Children); + command.addObjectID(checkedThreadGroupID); + command.setLength(); + + log.display("Waiting for reply to command"); + ReplyPacket reply = debugee.receiveReplyFor(command); + log.display("Valid reply packet received"); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + threads = reply.getInt(); + log.display(" threads: " + threads); + + threadIDs = new long[threads]; + + for (int j = 0; j < threads; j++) { + long threadID = reply.getObjectID(); + log.display(" #" + j + " threadID: " + threadID); + threadIDs[j] = threadID; + } + + if (threads < 0) { + log.complain("Negative number of threads in the thread group: " + threads); + success = false; + } + + if (threads > 0) { + log.display("Testing threads from thread group: #" + i); + found = true; + } + } + + if (!found) { + log.complain("No threads found in all top level thread groups"); + success = false; + } + + // begin test of JDWP command + + for (int i = 0; i < threads; i++) { + + long threadID = threadIDs[i]; + + log.display(""); + log.display("Getting ThreadGroup ID for " + i + " thread ID: " + + threadID); + log.display("Create command " + JDWP_COMMAND_NAME + + " with thread ID: " + threadID); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addObjectID(threadID); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long threadGroupID = reply.getObjectID(); + log.display(" group: " + threadGroupID); + + if (threadGroupID != checkedThreadGroupID) { + log.complain("Unexpected threadGroupID returned for a thread: " + threadGroupID + + " (expected: " + checkedThreadGroupID + ")"); + success = false; + } + + if (! reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + success = false; + } else { + log.display("Reply packet parsed successfully"); + } + + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Caught exception while testing JDWP command: " + e); + success = false; + } finally { + log.display(""); + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + } catch (Exception e) { + log.complain("Caught unexpected exception while communicating with debugee: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Caught unexpected exception while starting the test: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: ThreadReference (11) + * command: ThreadGroup (5) + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * returned threadGroupID of a thread is equal to the expected + * one for all threads from a top level threads group. + * Test consists of two compoments: + * debugger: threadgroup001 + * debuggee: threadgroup001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger prepares for testing JDWP command and finds + * top level thread group with a number threads and obtains + * ID's for this ThreadGroup and all its threads. + * Then, for each found thread debugger creates command packet for + * ThreadGroup command with the found checkedThreadGroupID as an argument, + * writes packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and extracts threadGroupID from it. Also test checks that extracted + * threadGroupID of a thread is equal to the expected one. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.ThreadReference.ThreadGroup.threadgroup001 + * nsk.jdwp.ThreadReference.ThreadGroup.threadgroup001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.ThreadReference.ThreadGroup.threadgroup001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.ThreadReference.ThreadGroup; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class threadgroup001a { + + public static void main(String args[]) { + threadgroup001a _threadgroup001a = new threadgroup001a(); + System.exit(threadgroup001.JCK_STATUS_BASE + _threadgroup001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return threadgroup001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.AllClasses; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class allclasses001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.AllClasses"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "allclasses001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.AllClasses"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.AllClasses; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allclasses001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + String classSignature = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int classes = reply.getInt(); + log.display(" classes: " + classes); + + int found = 0; + for (int i = 0; i < classes; i++) { + + byte refTypeTag = reply.getByte(); + log.display(" " + i + " refTypeTag: " + refTypeTag); + + long typeID = reply.getReferenceTypeID(); + log.display(" " + i + " typeID: " + typeID); + + String signature = reply.getString(); + log.display(" " + i + " signature: " + signature); + + int status = reply.getInt(); + log.display(" " + i + " status: " + status); + + if (signature.equals(classSignature)) { + found++; + log.display("FOUND: expected class signature: " + found + " time"); + } + } + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + if (classes < 0) { + log.complain("Negative number of returned classes: " + classes); + success = false; + } + + if (classes == 0) { + log.complain("No class returned"); + success = false; + } + + if (found <= 0) { + log.complain("No expected class signature found: " + classSignature); + success = false; + } + + if (found > 1) { + log.complain("Too many classes (" + found + ") found for signature: " + classSignature); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/AllClasses/allclasses001. + * VM Testbase keywords: [jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: AllClasses + * Test checks that debugee accept command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test sends AllClasses command and waits for a + * reply packet. + * Then test checks if the received reply packet has proper + * structure and extracts class signatures from the packet data. + * Also test check if debugee class signature is in the + * among the received classes. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee VM exits and exits too + * with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.AllClasses.allclasses001 + * nsk.jdwp.VirtualMachine.AllClasses.allclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.AllClasses.allclasses001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.AllClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class allclasses001a { + + public static void main(String args[]) { + allclasses001a _allclasses001a = new allclasses001a(); + System.exit(allclasses001.JCK_STATUS_BASE + _allclasses001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return allclasses001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.AllClassesWithGeneric; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * This test checks that the JDWP command AllClassesWithGeneric + * from the VirtualMachine command set returns generic signature + * information properly.
+ * Debuggee part of the test creates instances of several tested classes. Some + * of the classes are generic. Debugger part obtains signature information of + * all loaded classes by sending the tested JDWP command. Proper generic + * signature should be returned for each tested class which is generic, or + * an empty string for non-generic one. All tested classes should be found + * in reply packet as well. + */ +public class allclswithgeneric001 { + static final String DEBUGGEE_CLASS = + "nsk.jdwp.VirtualMachine.AllClassesWithGeneric.allclswithgeneric001t"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.AllClassesWithGeneric"; + static final int JDWP_COMMAND_ID = + JDWP.Command.VirtualMachine.AllClassesWithGeneric; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String[][] classes = { + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001t;", + "NULL"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001b;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001c;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001d;", + "Ljava/lang/Object;Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001if;"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001e;", + "NULL"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001if;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001f;", + "NULL"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001g;", + "Ljava/lang/Object;"}, + + {"Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001h;", + "Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001d;Lnsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001if2;"} + }; + + static final int CLS_NUM = classes.length; + + private int foundClasses[] = new int[CLS_NUM]; + + private Log log; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allclswithgeneric001().runThis(argv, out); + } + + public int runThis(String argv[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + boolean result = true; + + try { + for(int i=0; i>>>>> Create command " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("\nWaiting for reply packet ..."); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display(" ... Reply packet received:\n" + reply); + + log.display("\nChecking reply packet header"); + reply.checkHeader(command.getPacketID()); + + /* parsing of reply data: + int classes - Number of reference types that follow + + ---- Repeated 'classes' times: + byte refTypeTag - Kind of following reference type. + referenceTypeID typeID - Loaded reference type. + string signature - The JNI signature for the loaded reference type. + string genericSignature - The generic signature for the loaded reference type + or an empty string if there is none. + int status - The current class status. + ---- + */ + log.display("\nParsing reply packet:"); + reply.resetPosition(); + + int cls_num = reply.getInt(); + log.display("\tclasses: " + cls_num); + + for (int i=0; i found tested class " + + classes[idx][0] + " :" + + "\n\t\trefTypeTag: " + refTypeTag + + "\n\t\ttypeID: " + typeID + + "\n\t\tsignature: " + signature); + + if (genSignature.length() == 0) // a non-generic class + genSignature = "NULL"; + if (!genSignature.equals(classes[idx][1])) { + log.complain("TEST FAILED: Unexpected generic signature of tested class #" + + (i+1) + " (" + classes[idx][0] + ")" + + " in the reply packet:" + + "\n\tGot: " + genSignature + + "\n\tExpected: " + classes[idx][1] + "\n"); + result = false; + } + else + log.display("\t\tgeneric signature: " + genSignature); + + log.display("\t\tstatus: " + status); + } + } + + if (!reply.isParsed()) { + log.complain("TEST FAILED: Extra trailing bytes found in reply packet at: " + + reply.currentPosition()); + result = false; + } else + log.display("\n<<<<<< Reply packet parsed"); + /////// end test of JDWP command + + for (int i=0; i _allclswithgeneric001b = + new allclswithgeneric001b(); + allclswithgeneric001c _allclswithgeneric001c = + new allclswithgeneric001c(); + allclswithgeneric001e _allclswithgeneric001e = + new allclswithgeneric001e(); + allclswithgeneric001if _allclswithgeneric001if = + new allclswithgeneric001d(); + allclswithgeneric001f _allclswithgeneric001f = + new allclswithgeneric001f(); + allclswithgeneric001g _allclswithgeneric001g = + new allclswithgeneric001g(); + allclswithgeneric001h _allclswithgeneric001h = + new allclswithgeneric001h(); + + log.display("Debuggee VM started\nSending command: " + + allclswithgeneric001.COMMAND_READY); + pipe.println(allclswithgeneric001.COMMAND_READY); + + log.display("Waiting for command: " + + allclswithgeneric001.COMMAND_QUIT + " ..."); + String cmd = pipe.readln(); + log.display(" ... Received command: " + cmd + + "\nDebuggee is exiting ..."); + + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } +} + +/* + * Dummy classes used only for verifying generic signature information + * in a debugger. + */ + +class allclswithgeneric001b {} + +class allclswithgeneric001c {} + +interface allclswithgeneric001if { + int allclswithgeneric001ifMeth(); + + int allclswithgeneric001ifMeth2(I v); +} + +class allclswithgeneric001d implements allclswithgeneric001if { + public int allclswithgeneric001ifMeth() { + return 1; + } + + public int allclswithgeneric001ifMeth2(T v) { + return 2; + } +} + +class allclswithgeneric001e {} + +class allclswithgeneric001f extends allclswithgeneric001e implements allclswithgeneric001if { + public int allclswithgeneric001ifMeth() { + return 3; + } + + public int allclswithgeneric001ifMeth2(Object v) { + return 4; + } +} + +class allclswithgeneric001g {} + +interface allclswithgeneric001if2 {} + +class allclswithgeneric001h + extends allclswithgeneric001d + implements allclswithgeneric001if2 {} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.AllThreads; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class allthreads001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.AllThreads"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "allthreads001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.AllThreads"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.AllThreads; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allthreads001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + String classSignature = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int threads = reply.getInt(); + log.display(" threads: " + threads); + + if (threads < 0) { + log.complain("Negative number of returned threads: " + threads); + success = false; + } + + if (threads == 0) { + log.complain("No threads returned"); + success = false; + } + + for (int i = 0; i < threads; i++) { + long threadID = reply.getObjectID(); + log.display(" " + i + " threadID: " + threadID); + } + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/AllThreads/allthreads001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: AllThreads + * Test checks that debugee accept command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test sends AllThreads command and waits for a + * reply packet. + * Then test checks if the received reply packet has proper + * structure and extracts threadIDs list from the packet data. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee VM exits and exits too + * with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.AllThreads.allthreads001 + * nsk.jdwp.VirtualMachine.AllThreads.allthreads001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.AllThreads.allthreads001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.AllThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class allthreads001a { + + public static void main(String args[]) { + allthreads001a _allclasses001a = new allthreads001a(); + System.exit(allthreads001.JCK_STATUS_BASE + _allclasses001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return allthreads001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Capabilities; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; +import java.util.*; + +public class capabilities001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.Capabilities"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "capabilities001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.Capabilities"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Capabilities; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new capabilities001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + byte canWatchFieldModification = reply.getByte(); + log.display(" canWatchFieldModification: " + canWatchFieldModification); + + byte canWatchFieldAction = reply.getByte(); + log.display(" canWatchFieldAction: " + canWatchFieldAction); + + byte canGetBytecodes = reply.getByte(); + log.display(" canGetBytecodes: " + canGetBytecodes); + + byte canGetSyntheticAttribute = reply.getByte(); + log.display(" canGetSyntheticAttribute: " + canGetSyntheticAttribute); + + byte canGetOwnedMonitorInfo = reply.getByte(); + log.display(" canGetOwnedMonitorInfo: " + canGetOwnedMonitorInfo); + + byte canGetCurrentContendedMonitor = reply.getByte(); + log.display(" canGetCurrentContendedMonitor: " + canGetCurrentContendedMonitor); + + byte canGetMonitorInfo = reply.getByte(); + log.display(" canGetMonitorInfo: " + canGetMonitorInfo); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/Capabilities/capabilities001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: Capabilities + * Test checks that debugee accept command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test sends Capabilities command and waits for a + * reply packet. + * Then test checks if the received reply packet has proper + * structure and extracts capabilities info from the packet data. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee VM exits and exits too + * with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.Capabilities.capabilities001 + * nsk.jdwp.VirtualMachine.Capabilities.capabilities001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.Capabilities.capabilities001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Capabilities; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class capabilities001a { + + public static void main(String args[]) { + capabilities001a _capabilities001a = new capabilities001a(); + System.exit(capabilities001.JCK_STATUS_BASE + _capabilities001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return capabilities001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.CapabilitiesNew; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; +import java.util.*; + +public class capabilitiesnew001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.CapabilitiesNew"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "capabilitiesnew001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.CapabilitiesNew"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.CapabilitiesNew; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new capabilitiesnew001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + byte canWatchFieldModification = reply.getByte(); + log.display(" canWatchFieldModification: " + + canWatchFieldModification); + + byte canWatchFieldAction = reply.getByte(); + log.display(" canWatchFieldAction: " + + canWatchFieldAction); + + byte canGetBytecodes = reply.getByte(); + log.display(" canGetBytecodes: " + + canGetBytecodes); + + byte canGetSyntheticAttribute = reply.getByte(); + log.display(" canGetSyntheticAttribute: " + + canGetSyntheticAttribute); + + byte canGetOwnedMonitorInfo = reply.getByte(); + log.display(" canGetOwnedMonitorInfo: " + + canGetOwnedMonitorInfo); + + byte canGetCurrentContendedMonitor = reply.getByte(); + log.display(" canGetCurrentContendedMonitor: " + + canGetCurrentContendedMonitor); + + byte canGetMonitorInfo = reply.getByte(); + log.display(" canGetMonitorInfo: " + + canGetMonitorInfo); + + byte canRedefineClasses = reply.getByte(); + log.display(" canRedefineClasses: " + + canRedefineClasses); + + byte canAddMethod = reply.getByte(); + log.display(" canAddMethod: " + + canAddMethod); + + byte canUnrestrictedlyRedefineClasses = reply.getByte(); + log.display(" canUnrestrictedlyRedefineClasses: " + + canUnrestrictedlyRedefineClasses); + + byte canPopFrames = reply.getByte(); + log.display(" canPopFrames: " + + canPopFrames); + + byte canUseInstanceFilters = reply.getByte(); + log.display(" canUseInstanceFilters: " + + canUseInstanceFilters); + + byte canGetSourceDebugExtension = reply.getByte(); + log.display(" canGetSourceDebugExtension: " + + canGetSourceDebugExtension); + + byte canRequestVMDeathEvent = reply.getByte(); + log.display(" canRequestVMDeathEvent: " + + canRequestVMDeathEvent); + + byte canSetDefaultStratum = reply.getByte(); + log.display(" canSetDefaultStratum: " + + canSetDefaultStratum); + + for (int i = 16; i <=32; i++) { + byte reserved = reply.getByte(); + log.display(" reserved" + i + ": " + + reserved); + } + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001. + * VM Testbase keywords: [quick, jpda, jdwp, redefine] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: CapabilitiesNew + * Test checks that debugee accept command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test sends CapabilitiesNew command and waits for a + * reply packet. + * Then test checks if the received reply packet has proper + * structure and extracts capabilities info from the packet data. + * After JDWP command has been tested, test sends debugee VM + * signal to quit, waits for debugee VM exits and exits too + * with the proper exit code. + * COMMENTS + * This test is for JDK-1.4 or higher. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.CapabilitiesNew.capabilitiesnew001 + * nsk.jdwp.VirtualMachine.CapabilitiesNew.capabilitiesnew001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.CapabilitiesNew.capabilitiesnew001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.CapabilitiesNew; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class capabilitiesnew001a { + + public static void main(String args[]) { + capabilitiesnew001a _capabilitiesnew001a = new capabilitiesnew001a(); + System.exit(capabilitiesnew001.JCK_STATUS_BASE + _capabilitiesnew001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return capabilitiesnew001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ClassPaths; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class classpaths001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.ClassPaths"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "classpaths001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.ClassPaths"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.ClassPaths; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new classpaths001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String baseDir = reply.getString(); + log.display(" baseDir: " + baseDir); + + int classpaths = reply.getInt(); + log.display(" classpaths: " + classpaths); + + for (int i = 0; i < classpaths; i++) { + String path = reply.getString(); + log.display(" " + i + " path: " + path); + } + + int bootclasspaths = reply.getInt(); + log.display(" bootclasspaths: " + bootclasspaths); + + for (int i = 0; i < bootclasspaths; i++) { + String path = reply.getString(); + log.display(" " + i + " path: " + path); + } + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/ClassPaths/classpaths001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test perform checking for + * command set: VirtualMachine + * command: ClassPaths + * Test launches debuggee VM using support classes and sends + * ClassPaths command to it. Then test receives reply for this + * command and prints classpath and bootclasspath value + * from received reply. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.ClassPaths.classpaths001 + * nsk.jdwp.VirtualMachine.ClassPaths.classpaths001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.ClassPaths.classpaths001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ClassPaths; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class classpaths001a { + + public static void main(String args[]) { + classpaths001a _classpaths001a = new classpaths001a(); + System.exit(classpaths001.JCK_STATUS_BASE + _classpaths001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return classpaths001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ClassesBySignature; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class classbysig001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.ClassesBySignature"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "classbysig001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.ClassesBySignature"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.ClassesBySignature; + + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME; +// static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME + ";"; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new classbysig001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + String classSignature = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // begin test of JDWP command + + try { + log.display("Create command " + JDWP_COMMAND_NAME + + " with class signature: " + classSignature); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addString(classSignature); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int classes = reply.getInt(); + log.display(" classes: " + classes); + + for (int i = 0; i < classes; i++) { + + byte refTypeTag = reply.getByte(); + log.display(" " + i + " refTypeTag: " + refTypeTag); + + long typeID = reply.getReferenceTypeID(); + log.display(" " + i + " typeID: " + typeID); + + int status = reply.getInt(); + log.display(" " + i + " status: " + status); + } + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + if (classes < 0) { + log.complain("Negative number of returned classes: " + classes); + success = false; + } + + if (classes == 0) { + log.complain("No class returned for signature: " + classSignature); + success = false; + } + + if (classes > 1) { + log.complain("Too many classes returned for signature: " + classSignature); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test perform checking for + * command set: VirtualMachine + * command: ClassBySignature + * Test checks that debugee accept command and replies + * with correct reply packet. Also test checks that one + * and only one class will be found for specified class + * signature. + * First, test launches debuggee VM using support classes + * and connects to it. + * Than test sends ClassByName command with debugee class + * signature as an command argument and waits for a reply. + * Than test checks if the received reply packet has proper + * structure and only one class is found for specified + * class signature. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.ClassesBySignature.classbysig001 + * nsk.jdwp.VirtualMachine.ClassesBySignature.classbysig001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.ClassesBySignature.classbysig001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ClassesBySignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class classbysig001a { + + public static void main(String args[]) { + classbysig001a _classbysig001a = new classbysig001a(); + System.exit(classbysig001.JCK_STATUS_BASE + _classbysig001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return classbysig001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.CreateString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; +import java.util.*; + +public class createstr001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.CreateString"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "createstr001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.CreateString"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.CreateString; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new createstr001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + String stringValue = "Testing string value"; + + // begin test of JDWP command + + try { + log.display("Create command " + JDWP_COMMAND_NAME + + " with string value: " + stringValue); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addString(stringValue); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + long stringID = reply.getObjectID(); + log.display(" stringID: " + stringID); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/CreateString/createstr001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test perform checking for + * command set: VirtualMachine + * command: CreateString + * Test checks that debugee accept command and replies + * with correct reply packet. + * First, test launches debuggee VM using support classes + * and connects to it. + * Than test sends CreateString command and waits for a reply. + * Than test checks if the received reply packet has proper + * structure and returns stringID. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.CreateString.createstr001 + * nsk.jdwp.VirtualMachine.CreateString.createstr001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.CreateString.createstr001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.CreateString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class createstr001a { + + public static void main(String args[]) { + createstr001a _createstr001a = new createstr001a(); + System.exit(createstr001.JCK_STATUS_BASE + _createstr001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return createstr001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Dispose; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class dispose001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.Dispose"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "dispose001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.Dispose"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Dispose; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new dispose001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + final ArgumentHandler argumentHandler = new ArgumentHandler(argv); + final Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + final Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + int bytesToWrite = 1024; + + // begin test of JDWP command + + try { + log.display("Creating command packet for " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + log.display("Reply packet parsed successfully"); + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + +/* + // check if transport connection has been actually closed + + if (success) { + + log.display("Trying to write VirtualMachine.Version command packet " + + "to the closed Transport connection"); + + try { + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Version); + transport.write(command); + + log.complain("Command packet successfully written to the closed transport channel\n" + + "without any I/O exception thrown"); + success = false; + } catch (IOException e) { + log.display("Caught expected IOException:\n\t" + e); + } + + } +*/ + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/Dispose/dispose001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for: + * command set: VirtualMachine + * command: Dispose + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: dispose001 + * debuggee: dispose001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Then debugger creates command packet for Dispose command, + * writes packet to the transport channel, and waits for a reply + * packet. + * When reply packet is received debugger parses the packet structure. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.Dispose.dispose001 + * nsk.jdwp.VirtualMachine.Dispose.dispose001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.Dispose.dispose001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Dispose; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class dispose001a { + + public static void main(String args[]) { + dispose001a _dispose001a = new dispose001a(); + System.exit(dispose001.JCK_STATUS_BASE + _dispose001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return dispose001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.DisposeObjects; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.DisposeObjects. + * + * See disposeobj001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class disposeobj001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.DisposeObjects"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "disposeobj001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "VirtualMachine.DisposeObjects"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.DisposeObjects; + + // tested class name and signature constants + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // Number of references to free for tested objects + static final int REF_COUNT = 3; + + // list of static fields with tested objects + static final String fieldsList[] = { + "objectValue", + "stringValue", + "classValue" + }; + static final int fieldsCount = fieldsList.length; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new disposeobj001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Obtaining requred data from debugee \n"); + + // query debuggee for classID of tested class + log.display("Getting classID by signature:\n" + + " " + TESTED_CLASS_SIGNATURE); + long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); + log.display(" got classID: " + classID); + + // query debuggee for objectIDs values of static fields + long objectIDs[] = getObjectIDs(classID); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(objectIDs); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Query debuggee for IDs of objects which are values of static fields. + */ + long[] getObjectIDs(long classID) { + long[] objectIDs = new long[fieldsCount]; + + for (int i = 0; i < fieldsCount; i++ ) { + String name = fieldsList[i]; + + log.display("Getting fieldID of static field: " + name); + long fieldID = debugee.getClassFieldID(classID, name, true); + log.display(" got fieldID: " + fieldID); + + // query for objectID value REF_COUNT times + log.display("Getting " + REF_COUNT + " times value of static fieldID: " + + fieldID); + for (int j = 0; j < REF_COUNT; j++) { + JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); + log.display(" #" + i + ": got value: " + value); + + if (value.getTag() != JDWP.Tag.OBJECT + && value.getTag() != JDWP.Tag.STRING) { + throw new Failure("Not object value returned for static field \"" + + name + "\": " + value); + } + long objectID = ((Long)value.getValue()).longValue(); + + // check that returned objectID is the same + if (j > 0) { + if (objectID != objectIDs[i]) { + throw new Failure("Last request for object value returned" + + " unexpected objectID: " + objectID + + "(expected: " + objectIDs[i] + ")"); + } + } else { + objectIDs[i] = objectID; + } + } + } + return objectIDs; + } + + /** + * Perform testing JDWP command for specified TypeID. + */ + void testCommand(long objectIDs[]) { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display(" requested: " + fieldsCount); + command.addInt(fieldsCount); + + for (int i = 0; i < fieldsCount; i++) { + log.display(" object: " + objectIDs[i]); + command.addObjectID(objectIDs[i]); + log.display(" refCnt: " + REF_COUNT); + command.addInt(REF_COUNT); + } + + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: DisposeObjects + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: disposeobj001 + * debuggee: disposeobj001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Next, debugger obtains classID and also objectIDs as values of + * the static fields. Debugger queries each objectID value REF_COUNT + * times to increase references count for objects on back-end. + * Then, debugger creates command packet for VirtualMachine.DisposeObjects + * command with the found methodIDs as arguments, writes packet to + * the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks that the received reply packet contains no data. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.DisposeObjects.disposeobj001 + * nsk.jdwp.VirtualMachine.DisposeObjects.disposeobj001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.DisposeObjects.disposeobj001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.DisposeObjects; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class disposeobj001a { + + public static void main(String args[]) { + disposeobj001a _disposeobj001a = new disposeobj001a(); + System.exit(disposeobj001.JCK_STATUS_BASE + _disposeobj001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // ensure tested class loaded + log.display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + log.display("Sending signal to debugger: " + disposeobj001.READY); + pipe.println(disposeobj001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + disposeobj001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(disposeobj001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + disposeobj001.QUIT + ")"); + log.display("Debugee FAILED"); + return disposeobj001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return disposeobj001.PASSED; + } + + // tested class + public static class TestedClass { + + // tested objects + static Object objectValue = new Object(); + static String stringValue = new String(); + static TestedClass classValue = new TestedClass(); + + int foo = 0; + + TestedClass() { + foo = 100; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Exit; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class exit001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.Exit"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "exit001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.Exit"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Exit; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new exit001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + final ArgumentHandler argumentHandler = new ArgumentHandler(argv); + final Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + final Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + + // Linux returns only 8 least significant bits of exit status - see #4459019 bug. + int expectedExitCode = 0x0F; + + // begin test of JDWP command + + try { + log.display("Creating command packet for " + JDWP_COMMAND_NAME + + " with exit code: " + expectedExitCode); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addInt(expectedExitCode); + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // check if debugee has been actually terminated + + if (success) { + int waittime = argumentHandler.getWaitTime() * 60; // seconds + int pause = 1; // seconds + int tries = waittime / pause; + success = false; + + for (int i = 0; i < tries; i++) { + if (debugee.terminated()) { + log.display("Debugee has been terminated successfully"); + success = true; + break; + } + try { + Thread.currentThread().sleep(pause * 1000); + } catch (InterruptedException e) { + log.complain("Interrupted exception catched: " + e); + } + } + if (! success) { + log.complain("Debugee has not been terminated by request"); + } + } + + // check if debugee exit code is as expected + + if (success) { + int exitCode = debugee.getStatus(); + log.display("Debugee exit code is: " + exitCode); + if (exitCode != expectedExitCode) { + log.complain("Debugee exit code is not equal to expected: " + expectedExitCode); + success = false; + } + } + + // end test of JDWP command + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/Exit/exit001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: Exit + * Test checks that debugee accept command and replies + * with correct reply packet. Also test checks that + * debugee is actually resumed by the command. + * First, test launches debuggee VM using support classes + * and connects to it. + * Then test sends Exit command with particular exit code + * and waits for a reply packet. + * Then test checks if the received reply packet has proper + * structure. Then test checks if debugee process is actually + * terminated with requested exit code. If debugee is not + * terminated for the specified in WAITTIME timeout test + * complains about an error. + * After JDWP command has been tested, test exits too + * with a proper exit code. + * COMMENTS: + * Modified due to fix of the bug: + * 4759453 TEST_BUG: tests against VirtualMachine.exit(int) should be corrected for Mantis + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.Exit.exit001 + * nsk.jdwp.VirtualMachine.Exit.exit001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.Exit.exit001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Exit; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class exit001a { + + public static void main(String args[]) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = argumentHandler.createDebugeeLog(); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + /* + * In this test debugger kills debuggee using VirtualMachine.exit, so + * standard JDWP tests communication protocol isn't used here + */ + try { + Thread.sleep(Long.MAX_VALUE); + } catch (Throwable t) { + // ignore all exceptions + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.HoldEvents; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.HoldEvents. + * + * See holdevents001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class holdevents001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.HoldEvents"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "holdevents001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "VirtualMachine.HoldEvents"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.HoldEvents; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new holdevents001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + } finally { + + log.display("\n>>> Finishing test \n"); + + // finally release events + log.display("Releasing events into debuggee"); + releaseEvents(); + + // quit debugee + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Release events into debuggee. + */ + void releaseEvents() { + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.ReleaseEvents); + ReplyPacket reply = debugee.receiveReplyFor(command); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no data in reply packet + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/HoldEvents/holdevents001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: HoldEvents + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: holdevents001 + * debuggee: holdevents001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Then, debugger creates command packet for VirtualMachine.HoldEvents + * command with no out data, writes packet to the transport channel, + * and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks that the received reply packet contains no data. + * Finally, debugger releases debuggee's events, sends debuggee signal + * to quit, waits for it exits and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.HoldEvents.holdevents001 + * nsk.jdwp.VirtualMachine.HoldEvents.holdevents001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.HoldEvents.holdevents001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.HoldEvents; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class holdevents001a { + + public static void main(String args[]) { + holdevents001a _holdevents001a = new holdevents001a(); + System.exit(holdevents001.JCK_STATUS_BASE + _holdevents001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // send debugger signal READY + log.display("Sending signal to debugger: " + holdevents001.READY); + pipe.println(holdevents001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + holdevents001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(holdevents001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + holdevents001.QUIT + ")"); + log.display("Debugee FAILED"); + return holdevents001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return holdevents001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.HoldEvents; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.HoldEvents. + * + * See holdevents002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * + * @see #runIt() + */ +public class holdevents002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.HoldEvents"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "holdevents002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "VirtualMachine.HoldEvents"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.HoldEvents; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.BREAKPOINT; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + static final byte TESTED_EVENT_MODIFIER = JDWP.EventModifierKind.LOCATION_ONLY; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of field and method of tested class + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = holdevents002a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedMethodID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new holdevents002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Get debuggee prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + + log.display("Holding events into debuggee"); + holdEvents(); + log.display(" ... events held"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for BREAKPOINT event NOT occured + log.display("Waiting for BREAKPOINT event NOT received"); + waitForBreakpointEvent(); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debuggee for testing. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for breakpoint method + log.display("Getting breakpoint methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // make request for BREAKPOINT event + log.display("Making request for BREAKPOINT event at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + eventRequestID = debugee.requestBreakpointEvent(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... got requestID: " + eventRequestID); + } + + /** + * Hold events into debuggee. + */ + void holdEvents() { + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.HoldEvents); + ReplyPacket reply = debugee.receiveReplyFor(command); + } + + /** + * Wait for requested BREAKPOINT event NOT occured. + */ + void waitForBreakpointEvent() { + + EventPacket eventPacket = new EventPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for event packet"); + transport.setReadTimeout(timeout); + transport.read(eventPacket); + log.display(" ... event packet received:\n" + eventPacket); + } catch (IOException e) { + log.display("No event packet received for default timeout:\n\t" + e); + log.display("Requested BREAKPOINT event is not received after holding events"); + return; + } + + log.complain("An event received after holding events into debuggee"); + log.display(""); + + // check reply packet header + try{ + log.display("Checking header of event packet"); + eventPacket.checkHeader(); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Bad header of received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in received event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in received event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Unexpected VM_DEATH event received intead of BREAKPOINT event"); + success = false; + dead = true; + return; + } else if (eventKind == JDWP.EventKind.BREAKPOINT) { + log.complain("Hold BREAKPOINT event received in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.BREAKPOINT + ")"); + success = false; + } else { + log.complain("Unexpected eventKind of event " + i + " in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.BREAKPOINT + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in BREAKPOINT event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/HoldEvents/holdevents002. + * VM Testbase keywords: [jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: HoldEvents + * event kind: BREAKPOINT + * Test checks that no requested BREAKPOINT events received from + * debuggee after holding events. + * Test consists of two compoments: + * debugger: holdevents002 + * debuggee: holdevents002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and requests an + * BREAKPOINT event for some location into tested class. + * Then, debugger uses tesed command VirtualMachine.HoldEvents to + * hold events into debuggee and resumes debuggee to allow it to + * reach the breakpoint. Debugger waits for WAITTIME timeout for + * an event packet. If no event packet received, tests passes. + * If requested BREAKPOINT or any other event received? test failed. + * Finally, debugger disconnectes debuggee, waits for it exit + * and exits too with proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.HoldEvents.holdevents002 + * nsk.jdwp.VirtualMachine.HoldEvents.holdevents002a + * @run main/othervm/timeout=420 PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.HoldEvents.holdevents002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.VirtualMachine.HoldEvents; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class holdevents002a { + + static final int BREAKPOINT_LINE = 80; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + holdevents002a _holdevents002a = new holdevents002a(); + System.exit(holdevents002.JCK_STATUS_BASE + _holdevents002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass object = new TestedClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + log.display("Invoking method with breakpoint"); + object.run(); + log.display(" ... method invoked"); + + // exit debugee + log.display("Debugee PASSED"); + return holdevents002.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + + public void run() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.IDSizes; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class idsizes001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.IDSizes"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "idsizes001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.IDSizes"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.IDSizes; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new idsizes001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int fieldIDSize = reply.getInt(); + log.display(" fieldIDSize: " + fieldIDSize); + + int methodIDSize = reply.getInt(); + log.display(" methodIDSize: " + methodIDSize); + + int objectIDSize = reply.getInt(); + log.display(" objectIdSize: " + objectIDSize); + + int referenceTypeIDSize = reply.getInt(); + log.display(" referenceTypeIDSize: " + referenceTypeIDSize); + + int frameIDSize = reply.getInt(); + log.display(" frameIdSize: " + frameIDSize); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/IDSizes/idsizes001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test perform checking for + * command set: VirtualMachine + * command: IDSizes + * Test launches debuggee VM using support classes and sends + * IDSizes command to it. Then test receives reply for this + * command and checks that the returned values of VM dependent + * type sizes are equal to the JDWP predefinite values. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.IDSizes.idsizes001 + * nsk.jdwp.VirtualMachine.IDSizes.idsizes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.IDSizes.idsizes001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.IDSizes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class idsizes001a { + + public static void main(String args[]) { + idsizes001a _idsizes001a = new idsizes001a(); + System.exit(idsizes001.JCK_STATUS_BASE + _idsizes001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return idsizes001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @summary converted from VM Testbase nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001. + * VM Testbase keywords: [quick, jpda, jdwp, feature_jdk6_jpda, vm6, monitoring] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: InstanceCounts + * Test checks that debuggee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: instanceCounts001 + * debuggee: instanceCounts001a + * Debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with execution commands. + * Debuggee during startup creates instances of 'nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass1' + * and 'nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass2' reachable via references with types + * which should be supported by command VirtualMachine.InstanceCounts: + * - strong reference + * - soft reference + * - weak reference + * - phantom reference + * - JNI global reference + * - JNI local reference + * First, debugger obtains referenceTypeID for 'nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass1'. + * Then, debugger creates command packet for InstanceCounts command with the found referenceTypeID + * as an argument, writes packet to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure, extracts number of instances + * and checks that received value is correct. + * Then debugger repeat described above actions, but created command packet contains 2 referenceTypeIDs for + * 'nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass1' and 'nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass2'. + * Also, test performs check for case when incorrect data is sent in command: + * - create command with refTypesCount < 0, expect ILLEGAL_ARGUMENT error + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.instanceCounts001 + * nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.instanceCounts001a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.instanceCounts001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001; + +import java.io.*; +import nsk.share.Consts; +import nsk.share.jdwp.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class instanceCounts001 extends TestDebuggerType1 { + protected String getDebugeeClassName() { + return "nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.instanceCounts001a"; + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instanceCounts001().runIt(argv, out); + } + + private void testCommand(long typeIDs[], int refTypesCount, int[] expectedInstanceCounts, boolean expectError, int errorCode) { + try { + int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.InstanceCounts; + + log.display("Create command: " + JDWP.commandNames.get(JDWP_COMMAND_ID)); + log.display("refTypesCount = " + refTypesCount); + for (long typeID : typeIDs) + log.display("refType = " + typeID); + + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.addInt(refTypesCount); + + for (int i = 0; i < refTypesCount; i++) + command.addReferenceTypeID(typeIDs[i]); + + command.setLength(); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + ReplyPacket reply; + + reply = getReply(command, expectError, errorCode); + + if (expectError) + return; + + int counts = reply.getInt(); + log.display("counts = " + counts); + + // check received 'counts' value + if (counts != refTypesCount) { + setSuccess(false); + log.complain("Invalid 'counts' value, expected is: " + refTypesCount); + } + + // check received 'instanceCount' value for all classes + for (int i = 0; i < counts; i++) { + long instanceCount = reply.getLong(); + log.display("instanceCount = " + instanceCount); + + if (instanceCount != expectedInstanceCounts[i]) { + setSuccess(false); + log.complain("Unexpected value 'instanceCount': " + instanceCount + ", expected is " + expectedInstanceCounts[i]); + } + } + + if (!reply.isParsed()) { + setSuccess(false); + log.complain("Extra trailing bytes found in reply packet at: " + reply.currentPosition()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + String testClass1 = nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass1.class.getName(); + String testClass2 = nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.TestClass2.class.getName(); + + forceGC(); + pipe.println(instanceCounts001a.COMMAND_CREATE_TEST_INSTANCES); + + if (!isDebuggeeReady()) + return; + + int expectedCount = instanceCounts001a.expectedCount; + + String classNames[]; + + classNames = new String[] { createTypeSignature(testClass1) }; + + long typeIDs[]; + + typeIDs = new long[classNames.length]; + + // create valid command for 1 class + for (int i = 0; i < classNames.length; i++) + typeIDs[i] = debuggee.getReferenceTypeID(classNames[i]); + + testCommand(typeIDs, typeIDs.length, new int[] { expectedCount }, false, 0); + + classNames = new String[] { createTypeSignature(testClass1), createTypeSignature(testClass2) }; + + typeIDs = new long[classNames.length]; + + // create valid command for 2 classes + for (int i = 0; i < classNames.length; i++) + typeIDs[i] = debuggee.getReferenceTypeID(classNames[i]); + + testCommand(typeIDs, typeIDs.length, new int[] { expectedCount, expectedCount }, false, 0); + + // create command with refTypesCount < 0, expect ILLEGAL_ARGUMENT error + testCommand(typeIDs, -1, new int[] { expectedCount }, true, JDWP.Error.ILLEGAL_ARGUMENT); + resetStatusIfGC(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001; + +import java.util.ArrayList; +import nsk.share.ReferringObjectSet; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdwp.*; + +class TestClass1 { + +} + +class TestClass2 { + +} + +public class instanceCounts001a extends AbstractJDWPDebuggee { + public static final int expectedCount = HeapwalkingDebuggee.includedIntoInstancesCountTypes.size(); + + public static final String COMMAND_CREATE_TEST_INSTANCES = "COMMAND_CREATE_TEST_INSTANCES"; + + private ArrayList referrers = new ArrayList(); + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_CREATE_TEST_INSTANCES)) { + for (String referenceType : HeapwalkingDebuggee.includedIntoInstancesCountTypes) { + referrers.add(new ReferringObjectSet(new TestClass1(), 1, referenceType)); + referrers.add(new ReferringObjectSet(new TestClass2(), 1, referenceType)); + } + + return true; + } + + return false; + } + + public static void main(String args[]) { + new instanceCounts001a().doTest(args); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.RedefineClasses; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.RedefineClasses. + * + * See redefinecls001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class redefinecls001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_REDEFINE_CLASSES; + static final String VM_CAPABILITY_NAME = "canRedefineClasses"; + + // package and classes names + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.RedefineClasses"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "redefinecls001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command + static final String JDWP_COMMAND_NAME = "VirtualMachine.RedefineClasses"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.RedefineClasses; + + // tested class name and signature + static final String TESTED_CLASS_NAME = TEST_CLASS_NAME + "b"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // field and method names + static final String CONSTRUCTOR_FIELD_NAME = "constructorInvoked"; + static final String STATIC_METHOD_FIELD_NAME = "staticMethodInvoked"; + static final String OBJECT_METHOD_FIELD_NAME = "objectMethodInvoked"; + static final String BREAKPOINT_METHOD_NAME = "runIt"; + static final int BREAKPOINT_LINE_BEFORE = redefinecls001a.BREAKPOINT_LINE_BEFORE; + static final int BREAKPOINT_LINE_AFTER = redefinecls001a.BREAKPOINT_LINE_AFTER; + + // filename for redefined class +// 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS +// precomiled class was removed +// static final String REDEFINED_CLASS_FILE_NAME = "redefinecls001b.klass"; + static final String REDEFINED_CLASS_FILE_NAME = "newclass" + + File.separator + PACKAGE_NAME.replace('.',File.separatorChar) + + File.separator + "redefinecls001b.class"; +// static final String REDEFINED_CLASS_DIR = "."; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + String testDir = null; + boolean dead = false; + boolean success = true; + + // data obtained from debuggee + long debugeeClassID = 0; + long testedClassID = 0; + long breakpointMethodID = 0; + ByteBuffer redefinedClassBytes = null; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new redefinecls001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); // minutes + timeout = waitTime * 60 * 1000; // milliseconds + + // get testDir as first positional parameter + String args[] = argumentHandler.getArguments(); + if (args.length < 1) { + log.complain("Test dir required as the first positional argument"); + return FAILED; + } + testDir = args[0]; + + // execute test and display results + try { + log.display("\n>>> Loading redefined class \n"); + + // load class file for redefined class + log.display("Loading bytecode of redefined class from file: " + + REDEFINED_CLASS_FILE_NAME); + redefinedClassBytes = loadClassBytes(REDEFINED_CLASS_FILE_NAME, testDir); + log.display(" ... loaded bytes: " + redefinedClassBytes.length()); + + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee VM"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debuggee launched"); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for VM_INIT event + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // check for VM capability + log.display("\n>>> Checking VM capability \n"); + log.display("Getting new VM capability: " + VM_CAPABILITY_NAME); + boolean capable = debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME); + log.display(" ... got VM capability: " + capable); + + // exit as PASSED if this capability is not supported + if (!capable) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // prepare debuggee for testing and obtain required data + log.display("\n>>> Getting prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>> Testing JDWP command \n"); + testCommand(); + + // check command results + if (success) { + log.display("\n>>> Checking result of tested command \n"); + checkResult(); + } + + // finish debuggee + log.display("\n>> Finishing debuggee \n"); + + // resume debuggee after testing command + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // wait for VM_DEATH event + log.display("Waiting for VM_DEATH event"); + debugee.waitForVMDeath(); + log.display(" ... VM_DEATH event received"); + dead = true; + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + log.display("\n>>> Finishing test \n"); + + // disconnect debugee and wait for its exit + if (debugee != null) { + quitDebugee(); + } + } + + // check result + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + out.println("TEST PASSED"); + return PASSED; + } + + /** + * Get debuggee prepared for testing and obtain required data. + */ + void prepareForTest() { + // wait for debuggee and tested classes loaded on debuggee startup + log.display("Waiting for classes loaded:" + + "\n\t" + DEBUGEE_CLASS_NAME + + "\n\t" + TESTED_CLASS_NAME); + String classNames[] = {DEBUGEE_CLASS_NAME, TESTED_CLASS_NAME}; + long classIDs[] = debugee.waitForClassesLoaded(classNames, + JDWP.SuspendPolicy.ALL); + debugeeClassID = classIDs[0]; + log.display(" ... debuggee class loaded with classID: " + debugeeClassID); + testedClassID = classIDs[1]; + log.display(" ... tested class loaded with classID: " + testedClassID); + log.display(""); + + // set breakpoint before redefinition and wait for debugee reached it + log.display("Waiting for breakpoint before redefiniton reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_BEFORE); + long threadID = debugee.waitForBreakpointReached(debugeeClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE_BEFORE, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint before redefinition reached with threadID: " + threadID); + log.display(""); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + int length = redefinedClassBytes.length(); + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" classes: " + 1); + command.addInt(1); + log.display(" refTypeID: " + testedClassID); + command.addReferenceTypeID(testedClassID); + log.display(" classfile: " + length + " bytes"); + command.addInt(length); + log.display(" classbytes:\n" + redefinedClassBytes); + command.addBytes(redefinedClassBytes.getBytes(), 0, length); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + // receive reply packet from debugee + ReplyPacket reply = new ReplyPacket(); + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display(" ... reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet for tested command:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking header of reply packet"); + reply.checkHeader(command.getPacketID()); + log.display(" ... packet header is correct"); + } catch (BoundException e) { + log.complain("Wrong header of reply packet for tested command:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet data:"); + reply.resetPosition(); + + // no reply data to parse + log.display(" no reply data"); + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + + log.display(" ... packed data parsed"); + } + + /** + * Check result of the tested JDWP command. + */ + void checkResult() { + // set breakpoint after redefinition and wait for debugee reached it + log.display("Waiting for breakpoint after redefiniton reached at: " + + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_AFTER); + long threadID = debugee.waitForBreakpointReached(debugeeClassID, + BREAKPOINT_METHOD_NAME, + BREAKPOINT_LINE_AFTER, + JDWP.SuspendPolicy.ALL); + log.display(" ... breakpoint after redefinition reached with threadID: " + threadID); + log.display(""); + + // check invoked methods + log.display("Getting value of static field: " + CONSTRUCTOR_FIELD_NAME); + JDWP.Value value = debugee.getStaticFieldValue(testedClassID, + CONSTRUCTOR_FIELD_NAME, JDWP.Tag.INT); + int constructorInvoked = ((Integer)value.getValue()).intValue(); + log.display(" ... got constructorInvoked: " + methodKind(constructorInvoked)); + + if (constructorInvoked != redefinecls001b.NOT_REDEFINED_METHOD_INVOKED) { + log.complain("Constructor has been invoked after class redefinition"); + success = false; + } + + log.display("Getting value of static field: " + STATIC_METHOD_FIELD_NAME); + value = debugee.getStaticFieldValue(testedClassID, + STATIC_METHOD_FIELD_NAME, JDWP.Tag.INT); + int staticMethodInvoked = ((Integer)value.getValue()).intValue(); + log.display(" ... got staticMethodInvoked: " + methodKind(staticMethodInvoked)); + + if (staticMethodInvoked != redefinecls001b.REDEFINED_METHOD_INVOKED) { + log.complain("Not redefined static method is invoked after class redefinition"); + success = false; + } + + log.display("Getting value of static field: " + OBJECT_METHOD_FIELD_NAME); + value = debugee.getStaticFieldValue(testedClassID, + OBJECT_METHOD_FIELD_NAME, JDWP.Tag.INT); + int objectMethodInvoked = ((Integer)value.getValue()).intValue(); + log.display(" ... got objectMethodInvoked: " + methodKind(objectMethodInvoked)); + + if (objectMethodInvoked != redefinecls001b.REDEFINED_METHOD_INVOKED) { + log.complain("Not redefined object method is invoked after class redefinition"); + success = false; + } + } + + /** + * Load class bytes form the given file. + */ + ByteBuffer loadClassBytes(String fileName, String dirName) { + String fileSep = System.getProperty("file.separator"); + String filePath = dirName + fileSep + fileName; + + String error = "Unable to read bytes from class file:\n\t" + filePath; + + int length = 0; + byte bytes[] = null; + try { + File file = new File(filePath); + length = (int)file.length(); + FileInputStream is = new FileInputStream(file); + bytes = new byte[length]; + int number = is.read(bytes); + if (number < 0) { + log.complain("EOF reached while reading bytes from file"); + throw new Failure(error); + } else if (number != length) { + log.complain("Unexpected number of bytes red from file: " + number + + " (expected: " + length + ")"); + throw new Failure(error); + } + is.close(); + } catch ( IOException e ) { + log.complain("Caught IOException while reading bytes from file:\n\t" + e); + throw new Failure(error); + } + ByteBuffer byteBuffer = new ByteBuffer(length, 0); + byteBuffer.addBytes(bytes, 0, length); + return byteBuffer; + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + + // return string representation of kind of invoked method + private static String methodKind(int kind) { + switch (kind) { + case redefinecls001b.METHOD_NOT_INVOKED: + return "METHOD_NOT_INVOKED"; + case redefinecls001b.REDEFINED_METHOD_INVOKED: + return "REDEFINED_METHOD_INVOKED"; + case redefinecls001b.NOT_REDEFINED_METHOD_INVOKED: + return "NOT_REDEFINED_METHOD_INVOKED"; + default: + return "UNKNOWN_METHOD_KIND"; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001. + * VM Testbase keywords: [quick, jpda, jdwp, redefine] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: RedefineClasses + * Test checks that debugee accept the command packet and + * replies with correct reply packet. Also test checks that + * after class redefinition invocation of static and object + * methods resuts in invocation of redefined methods, and + * no constructors are invoked. + * Test consists of two compoments: + * debugger: redefinecls001 + * debuggee: redefinecls001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * It also loads bytecode of redefined class from *.klass file. + * Next, debugger waits for tested classes are loaded, and breakpoint + * before class redefinition is reached. + * Then, debugger creates command packet for VirtualMachine.RedefineClasses + * command for the found classID and loaded bytecode, writes this packet + * to the transport channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks if no reply data returned in the packet. + * Then, debugger resumes debuggee to allow methods of redefined class + * to be invoked and waits for second breakpoint is reached. + * Upon their invocation redefined methods puts proper value into + * the special static fields of debuggee class. The debugger then + * checks these fields to verify if the redefined methods were invoked + * and no constructors were invoked. + * Finally, debugger disconnects debuggee, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * First positional argument for the test should be path to the test + * work directory where loaded *.klass file should be located. + * Test was updated according to rfe: + * 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS. + * redefinecl001b.ja was moved into newclass directory and renamed + * to redefinecl001b.java. + * The precompiled class file is created during test base build process. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build ExecDriver + * @build nsk.jdwp.VirtualMachine.RedefineClasses.redefinecls001 + * nsk.jdwp.VirtualMachine.RedefineClasses.redefinecls001a + * nsk.jdwp.VirtualMachine.RedefineClasses.redefinecls001b + * @run driver PropertyResolvingWrapper ExecDriver --cmd + * ${compile.jdk}/bin/javac + * -cp ${test.class.path} + * -d newclass + * newclass/redefinecls001b.java + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.RedefineClasses.redefinecls001 + * . + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/newclass/redefinecls001b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/newclass/redefinecls001b.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.RedefineClasses; + +import nsk.share.*; + +/** + * This class is for class redefinition. + */ +public class redefinecls001b { + + // values for tested fields + public static final int INITIAL_FIELD_VALUE = 111; + public static final int FINAL_FIELD_VALUE = 222; + + // values for method redefinition + public static final int METHOD_NOT_INVOKED = 0; + public static final int REDEFINED_METHOD_INVOKED = 10; + public static final int NOT_REDEFINED_METHOD_INVOKED = 20; + + // static field + public static int staticField = INITIAL_FIELD_VALUE; + // object field + public int objectField = INITIAL_FIELD_VALUE; + + public static Log log; + // fields for methods redefinition results + public static int constructorInvoked = METHOD_NOT_INVOKED; + public static int staticMethodInvoked = METHOD_NOT_INVOKED; + public static int objectMethodInvoked = METHOD_NOT_INVOKED; + + // constructor + public redefinecls001b(int value) { + log.display("Constructor invoked: REDEFINED"); + constructorInvoked = REDEFINED_METHOD_INVOKED; + objectField = value; + } + + // static method to be redefined + public static void testedStaticMethod() { + log.display("Static method invoked: REDEFINED"); + staticMethodInvoked = REDEFINED_METHOD_INVOKED; + + log.display("Static fields values:"); + log.display(" staticField: " + staticField + + " (expected: " + FINAL_FIELD_VALUE + ")"); + } + + // object method to be redefined + public void testedObjectMethod() { + log.display("Object method invoked: REDEFINED"); + objectMethodInvoked = REDEFINED_METHOD_INVOKED; + + log.display("Object fields values:"); + log.display(" objectField: " + objectField + + " (expected: " + FINAL_FIELD_VALUE + ")"); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.VirtualMachine.RedefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class redefinecls001a { + + // line nunber for breakpoint + public static final int BREAKPOINT_LINE_BEFORE = 76; + public static final int BREAKPOINT_LINE_AFTER = 86; + + // fields for methods redefinition results +// public static Integer constructorInvoked = Integer(redefinecls001.METHOD_NOT_INVOKED); +// public static Integer staticMethodInvoked = Integer(redefinecls001.METHOD_NOT_INVOKED); +// public static Integer objectMethodInvoked = Integer(redefinecls001.METHOD_NOT_INVOKED); + + // scaffold objects + static volatile ArgumentHandler argumentHandler = null; + static volatile Log log = null; + + public static void main(String args[]) { + System.exit(redefinecls001.JCK_STATUS_BASE + redefinecls001a.runIt(args, System.err)); + } + + public static int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // create tested thread + log.display("Creating object of tested class"); + redefinecls001b.staticField = redefinecls001b.FINAL_FIELD_VALUE; + redefinecls001b.log = log; + redefinecls001b object = new redefinecls001b(redefinecls001b.FINAL_FIELD_VALUE); + log.display(" ... object created"); + + // invoke tested method before redefinition + log.display("Invoking tested methods before redefinition"); + redefinecls001b.testedStaticMethod(); + object.testedObjectMethod(); + printInvocationResult(); + + log.display("\nBreakpoint line before redefinition reached"); + // next line is for breakpoint before redefinition + int foo = 0; // BREAKPOINT_LINE_BEFORE + + // invoke tested method after redefinition + log.display("Invoking tested methods after redefinition"); + redefinecls001b.testedStaticMethod(); + object.testedObjectMethod(); + printInvocationResult(); + + log.display("\nBreakpoint line after redefinition reached"); + // next line is for breakpoint after redefinition + foo = 1; // BREAKPOINT_LINE_AFTER + + log.display("Debugee PASSED"); + return redefinecls001.PASSED; + } + + // print information about kind of invoked methods + private static void printInvocationResult() { + log.display("Result of methods invokation:"); + log.display(" constructorInvoked: " + methodKind(redefinecls001b.constructorInvoked)); + log.display(" staticMethodInvoked: " + methodKind(redefinecls001b.staticMethodInvoked)); + log.display(" objectMethodInvoked: " + methodKind(redefinecls001b.objectMethodInvoked)); + } + + // return string representation of kind of invoked method + private static String methodKind(int kind) { + switch (kind) { + case redefinecls001b.METHOD_NOT_INVOKED: + return "METHOD_NOT_INVOKED"; + case redefinecls001b.REDEFINED_METHOD_INVOKED: + return "REDEFINED_METHOD_INVOKED"; + case redefinecls001b.NOT_REDEFINED_METHOD_INVOKED: + return "NOT_REDEFINED_METHOD_INVOKED"; + default: + return "UNKNOWN_METHOD_KIND"; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001b.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.RedefineClasses; + +import nsk.share.*; + +/** + * This class is to be redefined. + */ +public class redefinecls001b { + + // values for tested fields + public static final int INITIAL_FIELD_VALUE = 111; + public static final int FINAL_FIELD_VALUE = 222; + + // values for method redefinition + public static final int METHOD_NOT_INVOKED = 0; + public static final int REDEFINED_METHOD_INVOKED = 10; + public static final int NOT_REDEFINED_METHOD_INVOKED = 20; + + // static field + public static int staticField = INITIAL_FIELD_VALUE; + // object field + public int objectField = INITIAL_FIELD_VALUE; + + public static Log log; + // fields for methods redefinition results + public static int constructorInvoked = METHOD_NOT_INVOKED; + public static int staticMethodInvoked = METHOD_NOT_INVOKED; + public static int objectMethodInvoked = METHOD_NOT_INVOKED; + + // constructor + public redefinecls001b(int value) { + log.display("Constructor invoked: NOT REDEFINED"); + constructorInvoked = NOT_REDEFINED_METHOD_INVOKED; + objectField = value; + } + + // static method to be redefined + public static void testedStaticMethod() { + log.display("Static method invoked: NOT REDEFINED"); + staticMethodInvoked = NOT_REDEFINED_METHOD_INVOKED; + + log.display("Static fields values:"); + log.display(" staticField: " + staticField + + " (expected: " + FINAL_FIELD_VALUE + ")"); + } + + // object method to be redefined + public void testedObjectMethod() { + log.display("Object method invoked: NOT REDEFINED"); + objectMethodInvoked = NOT_REDEFINED_METHOD_INVOKED; + + log.display("Object fields values:"); + log.display(" objectField: " + objectField + + " (expected: " + FINAL_FIELD_VALUE + ")"); // BREAKPOINT_LINE_BEFORE + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ReleaseEvents; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.ReleaseEvents. + * + * See releaseevents001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class releaseevents001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.ReleaseEvents"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "releaseevents001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "VirtualMachine.ReleaseEvents"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.ReleaseEvents; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new releaseevents001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + + // finally release events + log.display("Holding events into debuggee"); + holdEvents(); + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + } finally { + + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Hold events into debuggee. + */ + void holdEvents() { + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.HoldEvents); + ReplyPacket reply = debugee.receiveReplyFor(command); + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no data in reply packet + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: ReleaseEvents + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: releaseevents001 + * debuggee: releaseevents001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Before testing JDWP command debugger holds debuggee's events. + * Then, debugger creates command packet for VirtualMachine.ReleaseEvents + * command with no out data, writes packet to the transport channel, + * and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks that the received reply packet contains no data. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * COMMENTS + * Test fixed according to test bug: + * 4954298 TEST_BUG: typo in nsk/jdwp/VirtualMachine/ReleaseEvents/<*> tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents001 + * nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ReleaseEvents; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class releaseevents001a { + + public static void main(String args[]) { + releaseevents001a _releaseevents001a = new releaseevents001a(); + System.exit(releaseevents001.JCK_STATUS_BASE + _releaseevents001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // send debugger signal READY + log.display("Sending signal to debugger: " + releaseevents001.READY); + pipe.println(releaseevents001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + releaseevents001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(releaseevents001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + releaseevents001.QUIT + ")"); + log.display("Debugee FAILED"); + return releaseevents001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return releaseevents001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.ReleaseEvents; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.ReleaseEvents. + * + * See releaseevents002.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * + * @see #runIt() + */ +public class releaseevents002 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.ReleaseEvents"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "releaseevents002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "VirtualMachine.ReleaseEvents"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.ReleaseEvents; + static final byte TESTED_EVENT_KIND = JDWP.EventKind.BREAKPOINT; + static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; + static final byte TESTED_EVENT_MODIFIER = JDWP.EventModifierKind.LOCATION_ONLY; + + // name and signature of the tested class + static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; + static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; + + // name of field and method of tested class + static final String TESTED_METHOD_NAME = "run"; + static final int BREAKPOINT_LINE = releaseevents002a.BREAKPOINT_LINE; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + int waitTime = 0; // minutes + long timeout = 0; // milliseconds + boolean dead = false; + boolean success = true; + + // obtained data + long testedClassID = 0; + long testedMethodID = 0; + int eventRequestID = 0; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start test from JCK-compilant environment. + */ + public static int run(String argv[], PrintStream out) { + return new releaseevents002().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + waitTime = argumentHandler.getWaitTime(); + timeout = waitTime * 60 * 1000; + + // execute test and display results + try { + log.display("\n>>> Starting debugee \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + log.display(" ... debugee launched"); + log.display(""); + + // set timeout for debuggee responces + log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); + transport.setReadTimeout(timeout); + log.display(" ... timeout set"); + + // wait for debuggee started + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + log.display(" ... VM_INIT event received"); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + log.display(" ... size of VM-dependent types adjusted"); + + // get debuggee prepared for testing + log.display("\n>>> Get debuggee prepared for testing \n"); + prepareForTest(); + + // test JDWP command + log.display("\n>>> Testing JDWP command \n"); + + // hold events + log.display("Holding events into debuggee"); + holdEvents(); + log.display(" ... events held"); + + // resume debuggee + log.display("Resuming debuggee"); + debugee.resume(); + log.display(" ... debuggee resumed"); + + // release events + log.display("Release events into debuggee"); + releaseEvents(); + log.display(" ... events released"); + + // wait for BREAKPOINT event + log.display("Waiting for BREAKPOINT event"); + waitForBreakpointEvent(); + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + // check test results + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debuggee for testing. + */ + void prepareForTest() { + // wait for tested class loaded + log.display("Waiting for tested class loaded"); + testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); + log.display(" ... got classID: " + testedClassID); + log.display(""); + + // get methodID for breakpoint method + log.display("Getting breakpoint methodID by name: " + TESTED_METHOD_NAME); + testedMethodID = debugee.getMethodID(testedClassID, TESTED_METHOD_NAME, true); + log.display(" ... got methodID: " + testedMethodID); + + // make request for BREAKPOINT event + log.display("Making request for BREAKPOINT event at: " + + TESTED_METHOD_NAME + ":" + BREAKPOINT_LINE); + eventRequestID = debugee.requestBreakpointEvent(JDWP.TypeTag.CLASS, testedClassID, + testedMethodID, BREAKPOINT_LINE, + JDWP.SuspendPolicy.ALL); + log.display(" ... got requestID: " + eventRequestID); + } + + /** + * Hold events into debuggee. + */ + void holdEvents() { + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.HoldEvents); + ReplyPacket reply = debugee.receiveReplyFor(command); + } + + /** + * Release events into debuggee. + */ + void releaseEvents() { + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.ReleaseEvents); + ReplyPacket reply = debugee.receiveReplyFor(command); + } + + /** + * Wait for requested BREAKPOINT event NOT occured. + */ + void waitForBreakpointEvent() { + + // receive event + EventPacket eventPacket = null; + try { + eventPacket = debugee.receiveEvent(); + log.display("Event received after releasing events into debuggee"); + } catch (Failure e) { + log.complain("No requested event received after releasing events into debuggee:\n\t" + + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing event packet:"); + eventPacket.resetPosition(); + + // get suspendPolicy value + byte suspendPolicy = 0; + try { + suspendPolicy = eventPacket.getByte(); + log.display(" suspendPolicy: " + suspendPolicy); + } catch (BoundException e) { + log.complain("Unable to get suspendPolicy value from received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get events count + int events = 0; + try { + events = eventPacket.getInt(); + log.display(" events: " + events); + } catch (BoundException e) { + log.complain("Unable to get events count from received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check events count + if (events < 0) { + log.complain("Negative value of events number in received event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } else if (events != 1) { + log.complain("Invalid number of events in received event packet: " + + events + " (expected: " + 1 + ")"); + success = false; + } + + // extract each event + long eventThreadID = 0; + for (int i = 0; i < events; i++) { + log.display(" event #" + i + ":"); + + // get eventKind + byte eventKind = 0; + try { + eventKind = eventPacket.getByte(); + log.display(" eventKind: " + eventKind); + } catch (BoundException e) { + log.complain("Unable to get eventKind of event #" + i + " from received event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check eventKind + if (eventKind == JDWP.EventKind.VM_DEATH) { + log.display("Unexpected VM_DEATH event received intead of BREAKPOINT event"); + success = false; + dead = true; + return; + } else if (eventKind == JDWP.EventKind.BREAKPOINT) { + log.display("Expected BREAKPOINT event received in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.BREAKPOINT + ")"); + } else { + log.complain("Unexpected eventKind of event " + i + " in event packet: " + + eventKind + " (expected: " + JDWP.EventKind.BREAKPOINT + ")"); + success = false; + return; + } + + // get requestID + int requestID = 0; + try { + requestID = eventPacket.getInt(); + log.display(" requestID: " + requestID); + } catch (BoundException e) { + log.complain("Unable to get requestID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // check requestID + if (requestID != eventRequestID) { + log.complain("Unexpected requestID of event " + i + " in BREAKPOINT event packet: " + + requestID + " (expected: " + eventRequestID + ")"); + success = false; + } + + // get threadID + long threadID = 0; + try { + threadID = eventPacket.getObjectID(); + log.display(" threadID: " + threadID); + } catch (BoundException e) { + log.complain("Unable to get threadID of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + + // get location + JDWP.Location location = null; + try { + location = eventPacket.getLocation(); + log.display(" location: " + location); + } catch (BoundException e) { + log.complain("Unable to get location of event #" + i + " from BREAKPOINT event packet:\n\t" + + e.getMessage()); + success = false; + return; + } + } + + // check for extra data in event packet + if (!eventPacket.isParsed()) { + log.complain("Extra trailing bytes found in event packet at: " + + eventPacket.offsetString()); + success = false; + } + + log.display(" ... event packet parsed"); + } + + /** + * Disconnect debuggee and wait for it exited. + */ + void quitDebugee() { + if (debugee == null) + return; + + // disconnect debugee if not dead + if (!dead) { + try { + log.display("Disconnecting debuggee"); + debugee.dispose(); + log.display(" ... debuggee disconnected"); + } catch (Failure e) { + log.display("Failed to finally disconnect debuggee:\n\t" + + e.getMessage()); + } + } + + // wait for debugee exited + log.display("Waiting for debuggee exit"); + int code = debugee.waitFor(); + log.display(" ... debuggee exited with exit code: " + code); + + // analize debugee exit status code + if (code != JCK_STATUS_BASE + PASSED) { + log.complain("Debuggee FAILED with exit code: " + code); + success = false; + } + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: ReleaseEvents + * event kind: BREAKPOINT + * Test checks that requested BREAKPOINT event received from + * debuggee after holding and then releasing events. + * Test consists of two compoments: + * debugger: releaseevents002 + * debuggee: releaseevents002a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Next, debugger waits for tested class loaded and requests an + * BREAKPOINT event for some location into tested class. + * Then, debugger holds events into debuggee, resumes debuggee to + * allow it to reach breakpoint, and then releases events using + * tested command VirtualMachine.ReleaseEvents. Debugger waits for + * an event packet is received and checks if this packet is for + * requested BREAKPOINT event. + * Finally, debugger disconnectes debuggee, waits for it exit + * and exits too with proper exit code. + * COMMENTS + * Test fixed according to test bug: + * 4954298 TEST_BUG: typo in nsk/jdwp/VirtualMachine/ReleaseEvents/<*> tests + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents002 + * nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// THIS TEST IS LINE NUMBER SENSITIVE + +package nsk.jdwp.VirtualMachine.ReleaseEvents; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class releaseevents002a { + + static final int BREAKPOINT_LINE = 80; + + static ArgumentHandler argumentHandler = null; + static Log log = null; + + public static void main(String args[]) { + releaseevents002a _releaseevents002a = new releaseevents002a(); + System.exit(releaseevents002.JCK_STATUS_BASE + _releaseevents002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + argumentHandler = new ArgumentHandler(args); + log = new Log(out, argumentHandler); + + // ensure tested class is loaded + log.display("Creating object of tested class"); + TestedClass object = new TestedClass(); + log.display(" ... object created"); + + // invoke method with breakpoint + log.display("Invoking method with breakpoint"); + object.run(); + log.display(" ... method invoked"); + + // exit debugee + log.display("Debugee PASSED"); + return releaseevents002.PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + public TestedClass() { + foo = 1000; + } + + public void run() { + log.display("Breakpoint line reached"); + // next line is for breakpoint + foo = 0; // BREAKPOINT_LINE + log.display("Breakpoint line passed"); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Resume; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class resume001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.Resume"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "resume001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.Resume"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Resume; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new resume001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + final Log log = new Log(out, argumentHandler); + long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + final IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Caught exception: " + e); + success = false; + } + + // check if debugee has been actually resumed + + if (success) { + log.display("Waiting for debugee continues execution or timeout exceeds"); + + // separate thread for waiting for reply from debuggee + class TimeoutHandler extends Thread { + boolean success = false; + public void run() { + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + if (cmd.equals("ready")) { + success = true; + log.display("Debugee was resumed successfully"); + } else { + log.complain("Unexpected command received: " + cmd); + } + } + } + + // start separate thread + TimeoutHandler timeoutHandler = new TimeoutHandler(); + timeoutHandler.start(); + + // wait for thread finished or timeout exceeds + try { + timeoutHandler.join(timeout); + if (timeoutHandler.isAlive()) { + log.display("Interrupting thread because timeout exceeds"); + timeoutHandler.interrupt(); + } + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted: " + e); + } + + // check resuts + if (!timeoutHandler.success) { + log.complain("Debugee has not been resumed by command"); + success = false; + } + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/Resume/resume001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: Resume + * Test checks that debugee accept command and replies + * with correct reply packet. Also test checks that + * debugee is actually resumed by the command. + * First, test launches debuggee VM using support classes + * and connects to it. Debugee is launched in the suspend + * mode by default. + * Then test sends Resume command and waits for a + * reply packet. + * When reply is received test checks if the reply packet + * has proper structure. Then test waits for a signal + * from the resumed debuggee. If signal has not received + * after specified by WAITTIME timeout, test complains + * about an error. + * Finally, test sends debugee VM signal to quit, waits + * for debugee VM exits and exits too with a proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.Resume.resume001 + * nsk.jdwp.VirtualMachine.Resume.resume001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.Resume.resume001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class resume001a { + + public static void main(String args[]) { + resume001a _resume001a = new resume001a(); + System.exit(resume001.JCK_STATUS_BASE + _resume001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return resume001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.SetDefaultStratum; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +/** + * Test for JDWP command: VirtualMachine.SetDefaultStratum. + * + * See setdefstrat001.README for description of test execution. + * + * This class represents debugger part of the test. + * Test is executed by invoking method runIt(). + * JDWP command is tested in the method testCommand(). + * + * @see #runIt() + * @see #testCommand() + */ +public class setdefstrat001 { + + // exit status constants + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + + // communication signals constants + static final String READY = "ready"; + static final String QUIT = "quit"; + + // package and classes names constants + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.SetDefaultStratum"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "setdefstrat001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + // VM capability constatnts + static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_SET_DEFAULT_STRATUM; + static final String VM_CAPABILITY_NAME = "canSetDefaultStratum"; + + // tested JDWP command constants + static final String JDWP_COMMAND_NAME = "VirtualMachine.SetDefaultStratum"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.SetDefaultStratum; + + // new value for default startum + static final String NEW_DEFAULT_STRATUM = "test"; + + // usual scaffold objects + ArgumentHandler argumentHandler = null; + Log log = null; + Binder binder = null; + Debugee debugee = null; + Transport transport = null; + IOPipe pipe = null; + + // test passed or not + boolean success = true; + + // ------------------------------------------------------------------- + + /** + * Start test from command line. + */ + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + /** + * Start JCK-compilant test. + */ + public static int run(String argv[], PrintStream out) { + return new setdefstrat001().runIt(argv, out); + } + + // ------------------------------------------------------------------- + + /** + * Perform test execution. + */ + public int runIt(String argv[], PrintStream out) { + + // make log for debugger messages + argumentHandler = new ArgumentHandler(argv); + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debuggee + binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + transport = debugee.getTransport(); + pipe = debugee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + // work with prepared debuggee + try { + log.display("\n>>> Checking VM capability \n"); + + // check for VM capability + log.display("Checking VM capability: " + VM_CAPABILITY_NAME); + if (!debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME)) { + out.println("TEST PASSED: unsupported VM capability: " + + VM_CAPABILITY_NAME); + return PASSED; + } + + // perform testing JDWP command + log.display("\n>>> Testing JDWP command \n"); + testCommand(); + + } finally { + // quit debugee + log.display("\n>>> Finishing test \n"); + quitDebugee(); + } + + } catch (Failure e) { + log.complain("TEST FAILED: " + e.getMessage()); + success = false; + } catch (Exception e) { + e.printStackTrace(out); + log.complain("Caught unexpected exception while running the test:\n\t" + e); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + + /** + * Prepare debugee for testing and waiting for ready signal. + */ + void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debugee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + READY); + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + if (! signal.equals(READY)) { + throw new TestBug("Unexpected signal received from debugee: " + signal + + " (expected: " + READY + ")"); + } + } + + /** + * Sending debugee signal to quit and waiting for it exits. + */ + void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + QUIT); + pipe.println(QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + + // analize debugee exit status code + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED with exit code: " + code); + } else { + log.complain("Debugee FAILED with exit code: " + code); + success = false; + } + } + + /** + * Perform testing JDWP command. + */ + void testCommand() { + // create command packet and fill requred out data + log.display("Create command packet:"); + log.display("Command: " + JDWP_COMMAND_NAME); + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + log.display(" stratumID: " + NEW_DEFAULT_STRATUM); + command.addString(NEW_DEFAULT_STRATUM); + command.setLength(); + + // send command packet to debugee + try { + log.display("Sending command packet:\n" + command); + transport.write(command); + } catch (IOException e) { + log.complain("Unable to send command packet:\n\t" + e); + success = false; + return; + } + + ReplyPacket reply = new ReplyPacket(); + + // receive reply packet from debugee + try { + log.display("Waiting for reply packet"); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + } catch (IOException e) { + log.complain("Unable to read reply packet:\n\t" + e); + success = false; + return; + } + + // check reply packet header + try{ + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + log.complain("Bad header of reply packet:\n\t" + e.getMessage()); + success = false; + return; + } + + // start parsing reply packet data + log.display("Parsing reply packet:"); + reply.resetPosition(); + + // no data in reply packet + + // check for extra data in reply packet + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in reply packet at: " + + reply.offsetString()); + success = false; + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test performs checking for + * command set: VirtualMachine + * command: SetDefaultStratum + * Test checks that debugee accept the command packet and + * replies with correct reply packet. + * Test consists of two compoments: + * debugger: setdefstrat001 + * debuggee: setdefstrat001a + * First, debugger uses nsk.share support classes to launch debuggee + * and obtain Transport object, that represents JDWP transport channel. + * Also communication channel (IOPipe) is established between + * debugger and debuggee to exchange with synchronization signals. + * Debugger uses VirtualMachine.CapabilitiesNew command to check + * VM capability canSetDefaultStratum before testing JDWP command. + * Then, debugger creates command packet for VirtualMachine.SetDefaultStratum + * command with new string value, writes packet to the transport + * channel, and waits for a reply packet. + * When reply packet is received, debugger parses the packet structure + * and checks that the received reply packet contains no data. + * Finally, debugger sends debuggee signal to quit, waits for it exits + * and exits too with the proper exit code. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.SetDefaultStratum.setdefstrat001 + * nsk.jdwp.VirtualMachine.SetDefaultStratum.setdefstrat001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.SetDefaultStratum.setdefstrat001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.SetDefaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +/** + * This class represents debuggee part in the test. + */ +public class setdefstrat001a { + + public static void main(String args[]) { + setdefstrat001a _setdefstrat001a = new setdefstrat001a(); + System.exit(setdefstrat001.JCK_STATUS_BASE + _setdefstrat001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + //make log for debugee messages + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + + // make communication pipe to debugger + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + + // send debugger signal READY + log.display("Sending signal to debugger: " + setdefstrat001.READY); + pipe.println(setdefstrat001.READY); + + // wait for signal QUIT from debugeer + log.display("Waiting for signal from debugger: " + setdefstrat001.QUIT); + String signal = pipe.readln(); + log.display("Received signal from debugger: " + signal); + + // check received signal + if (! signal.equals(setdefstrat001.QUIT)) { + log.complain("Unexpected communication signal from debugee: " + signal + + " (expected: " + setdefstrat001.QUIT + ")"); + log.display("Debugee FAILED"); + return setdefstrat001.FAILED; + } + + // exit debugee + log.display("Debugee PASSED"); + return setdefstrat001.PASSED; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.TopLevelThreadGroups; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class threadgroups001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.TopLevelThreadGroups"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "threadgroups001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.TopLevelThreadGroups"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.TopLevelThreadGroups; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new threadgroups001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + int groups = reply.getInt(); + log.display(" groups: " + groups); + + for (int i = 0; i < groups; i++) { + long threadGroupID = reply.getObjectID(); + log.display(" " + i + " threadGroupID: " + threadGroupID); + } + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + if (groups < 0) { + log.complain("Negative number of returned thread groups: " + groups); + success = false; + } + + if (groups == 0) { + log.complain("No thread groups returned: " + groups); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test perform checking for + * command set: VirtualMachine + * command: ClassPaths + * Test launches debuggee VM using support classes and sends + * ClassPaths command to it. Then test receives reply for this + * command and prints classpath and bootclasspath value + * from received reply. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.TopLevelThreadGroups.threadgroups001 + * nsk.jdwp.VirtualMachine.TopLevelThreadGroups.threadgroups001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.TopLevelThreadGroups.threadgroups001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.TopLevelThreadGroups; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +import java.io.*; + +public class threadgroups001a { + + public static void main(String args[]) { + threadgroups001a _threadgroups001a = new threadgroups001a(); + System.exit(threadgroups001.JCK_STATUS_BASE + _threadgroups001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return threadgroups001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Version; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class version001 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.Version"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "version001"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.Version"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Version; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new version001().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String description = reply.getString(); + log.display(" description: " + description); + + int jdwpMajor = reply.getInt(); + log.display(" jdwpMajor: " + jdwpMajor); + + int jdwpMinor = reply.getInt(); + log.display(" jdwpMinor: " + jdwpMinor); + + String vmVersion = reply.getString(); + log.display(" vmVersion: " + vmVersion); + + String vmName = reply.getString(); + log.display(" vmName: " + vmName); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/Version/version001. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test perform checking for + * command set: VirtualMachine + * command: Version + * Test launches debuggee VM using support classes and sends + * Version command to it. Then test receives reply for this + * command and prints version information from that reply. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.Version.version001 + * nsk.jdwp.VirtualMachine.Version.version001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.Version.version001 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Version; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class version001a { + + public static void main(String args[]) { + version001a _version001a = new version001a(); + System.exit(version001.JCK_STATUS_BASE + _version001a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return version001.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Version; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class version002 { + static final int JCK_STATUS_BASE = 95; + static final int PASSED = 0; + static final int FAILED = 2; + static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.Version"; + static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "version002"; + static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; + + static final String JDWP_COMMAND_NAME = "VirtualMachine.Version"; + static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Version; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new version002().runIt(argv, out); + } + + public int runIt(String argv[], PrintStream out) { + + boolean success = true; + + try { + ArgumentHandler argumentHandler = new ArgumentHandler(argv); + Log log = new Log(out, argumentHandler); + + try { + + Binder binder = new Binder(argumentHandler, log); + log.display("Start debugee VM"); + Debugee debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); + Transport transport = debugee.getTransport(); + IOPipe pipe = debugee.createIOPipe(); + + log.display("Waiting for VM_INIT event"); + debugee.waitForVMInit(); + + log.display("Querying for IDSizes"); + debugee.queryForIDSizes(); + + log.display("Resume debugee VM"); + debugee.resume(); + + log.display("Waiting for command: " + "ready"); + String cmd = pipe.readln(); + log.display("Received command: " + cmd); + + // begin test of JDWP command + + try { + CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); + // A properly formed CommandPacket has JDWP.Flag.NONE + // for the 'flags' field. Set the 'flags' field to '!' + // simulate a bad value in the printable ASCII range. + // '!' == 0x21 which means the bad value also does not + // have the JDWP.Flag.REPLY_PACKET (0x80) set. + command.setFlags((byte) '!'); + + log.display("Sending command packet:\n" + command); + transport.write(command); + + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + + if (true) { + // In this test (compared to version001), we + // should never reach here because the debuggee + // should have thrown an IOException and printed + // this error message: + // ERROR: Received jdwpPacket with flags != 0x0 (actual=0x21) when a jdwpCmdPacket was expected. + + throw new Failure("Debuggee did not detect bad flags field."); + } + // The code below this point of the try-catch block is + // not reachable and could be deleted. It is left in + // place to ease porting of this test to earlier releases. + + log.display("Reply packet received:\n" + reply); + + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + + log.display("Parsing reply packet:"); + reply.resetPosition(); + + String description = reply.getString(); + log.display(" description: " + description); + + int jdwpMajor = reply.getInt(); + log.display(" jdwpMajor: " + jdwpMajor); + + int jdwpMinor = reply.getInt(); + log.display(" jdwpMinor: " + jdwpMinor); + + String vmVersion = reply.getString(); + log.display(" vmVersion: " + vmVersion); + + String vmName = reply.getString(); + log.display(" vmName: " + vmName); + + if (! reply.isParsed()) { + log.complain("Extra bytes in reply packet at: " + reply.currentPosition()); + success = false; + } + + } catch (IOException ie) { + // version001 expects to pass. + // This test expects to fail due to an IOException. + log.display("Expected IOException caught: " + ie); + success = true; + } catch (Exception e) { + log.complain("Exception catched: " + e); + success = false; + } + + // end test of JDWP command + + log.display("Sending command: " + "quit"); + pipe.println("quit"); + + log.display("Waiting for debugee exits"); + int code = debugee.waitFor(); + if (code == JCK_STATUS_BASE + PASSED) { + log.display("Debugee PASSED: " + code); + } else { + log.complain("Debugee FAILED: " + code); + success = false; + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + success = false; + } + + if (!success) { + log.complain("TEST FAILED"); + return FAILED; + } + + } catch (Exception e) { + out.println("Unexpected exception: " + e); + e.printStackTrace(out); + out.println("TEST FAILED"); + return FAILED; + } + + out.println("TEST PASSED"); + return PASSED; + + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 converted from VM Testbase nsk/jdwp/VirtualMachine/Version/version002. + * VM Testbase keywords: [quick, jpda, jdwp] + * VM Testbase readme: + * DESCRIPTION + * This test was derived from the version001 test. + * This test perform checking for + * command set: VirtualMachine + * command: Version + * Test launches debuggee VM using support classes and sends + * a malformed Version command to it. Then test expect the + * command to fail and debuggee VM to exit with an error. + * + * @library /vmTestbase /test/hotspot/jtreg/vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdwp.VirtualMachine.Version.version002 + * nsk.jdwp.VirtualMachine.Version.version002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdwp.VirtualMachine.Version.version002 + * -arch=${os.family}-${os.simpleArch} + * -verbose + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002a.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.jdwp.VirtualMachine.Version; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdwp.*; + +public class version002a { + + public static void main(String args[]) { + version002a _version002a = new version002a(); + System.exit(version002.JCK_STATUS_BASE + _version002a.runIt(args, System.err)); + } + + public int runIt(String args[], PrintStream out) { + ArgumentHandler argumentHandler = new ArgumentHandler(args); + Log log = new Log(out, argumentHandler); + log.display("Creating pipe"); + IOPipe pipe = argumentHandler.createDebugeeIOPipe(log); + log.display("Sending command: " + "ready"); + pipe.println("ready"); + log.display("Waiting for command: " + "quit"); + String command = pipe.readln(); + log.display("Received command: " + command); + log.display("Debugee PASSED"); + return version002.PASSED; + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest/JvmtiTest.c --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest/JvmtiTest.c Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest/JvmtiTest.c Thu May 31 13:39:26 2018 -0700 @@ -364,10 +364,10 @@ } #endif if (passed) { - debug_printf("Pass: currThreadTime(%ld) >= %2.0f%% of threadTime(%ld)\n", + debug_printf("Pass: currThreadTime(" JLONG_FORMAT ") >= %2.0f%% of threadTime(" JLONG_FORMAT ")\n", ctt, 100.0 - VARIANCE_PERCENT, tt); } else { - printf("FAIL: currThreadTime(%ld) < %2.0f%% of threadTime(%ld)\n", + printf("FAIL: currThreadTime(" JLONG_FORMAT ") < %2.0f%% of threadTime(" JLONG_FORMAT ")\n", ctt, 100.0 - VARIANCE_PERCENT, tt); iGlobalStatus = 2; } diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/AbstractJDWPDebuggee.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/AbstractJDWPDebuggee.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.share.jdwp; + +import nsk.share.jpda.AbstractDebuggeeTest; +import nsk.share.jpda.DebugeeArgumentHandler; + +public class AbstractJDWPDebuggee extends AbstractDebuggeeTest { + + /* + * Create argument handler handling options specific for JDWP tests + */ + protected DebugeeArgumentHandler createArgumentHandler(String args[]) { + return new ArgumentHandler(args); + } + + public static void main(String args[]) { + AbstractJDWPDebuggee debuggee = new AbstractJDWPDebuggee(); + debuggee.init(args); + debuggee.doTest(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/ArgumentHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/ArgumentHandler.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; +import nsk.share.jpda.*; + +import java.io.*; +import java.util.*; + +/** + * Parser for JDWP test's specific command-line arguments. + *

+ * ArgumentHandler handles JDWP test's specific + * arguments related to launching debugee VM using JDWP features + * in addition to general arguments recognized by + * DebugeeArgumentHandler and ArgumentParser. + *

+ * Following is the list of specific options recognized by + * AgrumentHandler: + *

    + *
  • -connector=[attaching|listening] - + * JDWP connection type + *
  • -transport=[socket|shmem] - + * JDWP transport kind + *
+ *

+ * See also list of arguments recognized by the base DebugeeArgumnethandler + * and ArgumentParser classes. + *

+ * See also description of ArgumentParser how to work with + * command line arguments and options. + * + * @see ArgumentParser + * @see DebugeeArgumentHandler + */ +public class ArgumentHandler extends DebugeeArgumentHandler { + + /** + * Keep a copy of raw command-line arguments and parse them; + * but throw an exception on parsing error. + * + * @param args Array of the raw command-line arguments. + * + * @throws NullPointerException If args==null. + * @throws IllegalArgumentException If Binder or Log options + * are set incorrectly. + * + * @see #setRawArguments(String[]) + */ + public ArgumentHandler(String args[]) { + super(args); + } + + /** + * Check if an option is admissible and has proper value. + * This method is invoked by parseArguments() + * + * @param option option name + * @param value string representation of value (could be an empty string) + * null if this option has no value + * @return true if option is admissible and has proper value + * false if otion is not admissible + * + * @throws BadOption if option has illegal value + * + * @see #parseArguments() + */ + protected boolean checkOption(String option, String value) { + return super.checkOption(option, value); + } + + /** + * Check options against inconcistence. + * This method is invoked by parseArguments() + * + * @see #parseArguments() + */ + protected void checkOptions() { + + if (isShmemTransport()) { + throw new BadOption("transport: shared memory transport is not supported yet"); + } + + super.checkOptions(); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Binder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Binder.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; +import nsk.share.jpda.*; + +import java.io.*; + +/** + * This class provides debugger with connection to debugee VM + * using JDWP protocol. + *

+ * This class provides abilities to launch and bind to debugee VM + * as described for base DebugeeBinder class, + * using raw JDWP protocol. + *

+ * When Binder is asked to bind to debugee by invoking + * bindToBebugee() method it launches process + * with debugee VM and makes connection to it using JDWP transport + * corresponding to value of command line options -connector + * and -transport. + * After debugee is launched and connection is established + * Binder constructs Debugee object, + * that provides abilities to interact with debugee VM. + * + * @see Debugee + * @see DebugeeBinder + */ +final public class Binder extends DebugeeBinder { + + /** + * Default message prefix for Binder object. + */ + public static final String LOG_PREFIX = "binder> "; + + /** + * Get version string. + */ + public static String getVersion () { + return "@(#)Binder.java %I% %E%"; + } + + // -------------------------------------------------- // + + /** + * Handler of command line arguments. + */ + private ArgumentHandler argumentHandler = null; + + /** + * Return argumentHandler of this binder. + */ + public ArgumentHandler getArgumentHandler() { + return argumentHandler; + } + + // -------------------------------------------------- // + + /** + * Make new Binder object with specified + * argumentHandler and log. + */ + public Binder (ArgumentHandler argumentHandler, Log log) { + super(argumentHandler, log); + this.argumentHandler = argumentHandler; + } + + // -------------------------------------------------- // + + /** + * Start debugee VM and establish JDWP connection to it. + */ + public Debugee bindToDebugee (String classToExecute) { + + Debugee debugee = null; + + prepareForPipeConnection(argumentHandler); + + if (argumentHandler.isLaunchedRemotely()) { + connectToBindServer(classToExecute); + debugee = launchDebugee(classToExecute); + } else { + debugee = launchDebugee(classToExecute); + debugee.redirectOutput(log); + } + + Finalizer finalizer = new Finalizer(debugee); + finalizer.activate(); + + Transport transport = debugee.connect(); + + return debugee; + } + + /** + * Launch debugee VM for specified class. + */ + public Debugee launchDebugee (String classToExecute) { + + try { + + if (argumentHandler.isLaunchedLocally()) { + LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(this); + String address = debugee.prepareTransport(argumentHandler); + if (address == null) + address = makeTransportAddress(); + String[] argsArray = makeCommandLineArgs(classToExecute, address); + debugee.launch(argsArray); + return debugee; + } + + if (argumentHandler.isLaunchedRemotely()) { + RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this); + String address = debugee.prepareTransport(argumentHandler); + if (address == null) + address = makeTransportAddress(); + String[] argsArray = makeCommandLineArgs(classToExecute, address); + debugee.launch(argsArray); + return debugee; + } + + if (argumentHandler.isLaunchedManually()) { + ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this); + String address = debugee.prepareTransport(argumentHandler); + if (address == null) + address = makeTransportAddress(); + String cmdLine = makeCommandLineString(classToExecute, address, "\""); + debugee.launch(cmdLine); + return debugee; + } + + throw new TestBug("Unexpected launching mode: " + + argumentHandler.getLaunchMode()); + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught exception while launching debugee:\n\t" + e); + } + } + +} + +/** + * Mirror of locally launched debugee. + */ +final class LocalLaunchedDebugee extends Debugee { + + /** Enwrap the existing VM mirror. */ + public LocalLaunchedDebugee (Binder binder) { + super(binder); + checkTermination = true; + } + + // ---------------------------------------------- // + + public void launch(String[] args) throws IOException { + String cmdLine = ArgumentHandler.joinArguments(args, "\""); + display("Starting java process:\n" + cmdLine); + process = binder.launchProcess(args); + } + + /** Return exit status of the debugee VM. */ + public int getStatus () { + return process.exitValue(); + } + + /** Check whether the debugee VM has been terminated. */ + public boolean terminated () { + if (process == null) + return true; + + try { + int value = process.exitValue(); + return true; + } catch (IllegalThreadStateException e) { + return false; + } + } + + // ---------------------------------------------- // + + /** Kill the debugee VM. */ + protected void killDebugee () { + super.killDebugee(); + if (!terminated()) { + log.display("Killing debugee VM process"); + process.destroy(); + } + } + + /** Wait until the debugee VM shutdown or crash. */ + protected int waitForDebugee () throws InterruptedException { + return process.waitFor(); + } + + /** Get a pipe to write to the debugee's stdin stream. */ + protected OutputStream getInPipe () { + return process.getOutputStream(); + } + + /** Get a pipe to read the debugee's stdout stream. */ + protected InputStream getOutPipe () { + return process.getInputStream(); + } + + /** Get a pipe to read the debugee's stderr stream. */ + protected InputStream getErrPipe () { + return process.getErrorStream(); + } +} + + +/** + * Mirror of remotely launched debugee. + */ +final class RemoteLaunchedDebugee extends Debugee { + + /** Enwrap the existing VM mirror. */ + public RemoteLaunchedDebugee (Binder binder) { + super(binder); + } + + // ---------------------------------------------- // + + public void launch(String[] args) throws IOException { + String cmdLine = ArgumentHandler.joinArguments(args, "\""); + display("Starting remote java process:\n" + cmdLine); + binder.launchRemoteProcess(args); + } + + /** Return exit status of the debugee VM. */ + public int getStatus () { + return binder.getRemoteProcessStatus(); + } + + /** Check whether the debugee VM has been terminated. */ + public boolean terminated () { + return binder.isRemoteProcessTerminated(); + } + + // ---------------------------------------------- // + + /** Kill the debugee VM. */ + protected void killDebugee () { + super.killDebugee(); + if (!terminated()) { + log.display("Killing debugee VM process"); + binder.killRemoteProcess(); + } + } + + /** Wait until the debugee VM shutdown or crash. */ + protected int waitForDebugee () { + return binder.waitForRemoteProcess(); + } + + /** Get a pipe to write to the debugee's stdin stream. */ + protected OutputStream getInPipe () { + return null; + } + + /** Get a pipe to read the debugee's stdout stream. */ + protected InputStream getOutPipe () { + return null; + } + + /** Get a pipe to read the debugee's stderr stream. */ + protected InputStream getErrPipe () { + return null; + } + + public void redirectStdout(OutputStream out) { + } + + public void redirectStdout(Log log, String prefix) { + } + + public void redirectStderr(OutputStream out) { + } + + public void redirectStderr(Log log, String prefix) { + } +} + + +/** + * Mirror of manually launched debugee. + */ +final class ManualLaunchedDebugee extends Debugee { + + private int exitCode = 0; + private boolean finished = false; + private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in)); + + /** Enwrap the existing VM mirror. */ + public ManualLaunchedDebugee (Binder binder) { + super(binder); + } + + // ---------------------------------------------- // + + public void launch(String commandLine) throws IOException { + putMessage("Launch target VM using such command line:\n" + + commandLine); + String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes"); + for ( ; ; ) { + if (answer.equals("yes")) + break; + if (answer.equals("no")) + throw new Failure ("Unable to manually launch debugee VM"); + answer = askQuestion("Wrong answer. Please type yes or no", "yes"); + } + } + + private void putMessage(String msg) { + System.out.println("\n>>> " + msg); + } + + private String askQuestion(String question, String defaultAnswer) { + try { + System.out.print("\n>>> " + question); + System.out.print(" [" + defaultAnswer + "] "); + System.out.flush(); + String answer = bin.readLine(); + if (answer.equals("")) + return defaultAnswer; + return answer; + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught exception while reading answer:\n\t" + e); + } + } + + /** Return exit status of the debugee VM. */ + public int getStatus () { + if (! terminated()) { + throw new Failure("Unable to get status of debugee VM: process still alive"); + } + return exitCode; + } + + /** Check whether the debugee VM has been terminated. */ + public boolean terminated () { + if(! finished) { + String answer = askQuestion("Has the VM exited?", "no"); + for ( ; ; ) { + if (answer.equals("no")) + return false; + if (answer.equals("yes")) { + finished = true; + waitForDebugee(); + break; + } + answer = askQuestion("Wrong answer. Please type yes or no", "yes"); + } + } + return finished; + } + + // ---------------------------------------------- // + + /** Kill the debugee VM. */ + protected void killDebugee () { + super.killDebugee(); + if (!terminated()) { + putMessage("Kill launched VM"); + String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes"); + for ( ; ; ) { + if (answer.equals("yes")) { + finished = true; + break; + } + if (answer.equals("no")) + throw new Failure ("Unable to manually kill debugee VM"); + answer = askQuestion("Wrong answer. Please type yes or no", "yes"); + } + } + } + + /** Wait until the debugee VM shutdown or crash. */ + protected int waitForDebugee () { + putMessage("Wait for launched VM to exit."); + String answer = askQuestion("What is VM exit code?", "95"); + for ( ; ; ) { + try { + exitCode = Integer.parseInt(answer); + break; + } catch (NumberFormatException e) { + answer = askQuestion("Wrong answer. Please type integer value", "95"); + } + } + finished = true; + return exitCode; + } + + /** Get a pipe to write to the debugee's stdin stream. */ + protected OutputStream getInPipe () { + return null; + } + + /** Get a pipe to read the debugee's stdout stream. */ + protected InputStream getOutPipe () { + return null; + } + + /** Get a pipe to read the debugee's stderr stream. */ + protected InputStream getErrPipe () { + return null; + } + + public void redirectStdout(OutputStream out) { + } + + public void redirectStdout(Log log, String prefix) { + } + + public void redirectStderr(OutputStream out) { + } + + public void redirectStderr(Log log, String prefix) { + } + + public void close() { + try { + bin.close(); + } catch (IOException e) { + log.display("WARNING: Caught IOException while closing InputStream"); + } + bin = null; + super.close(); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/BoundException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/BoundException.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +/** + * This exception is thrown when ByteBuffer parse errors are encountered. + */ +public class BoundException extends Exception { + public BoundException(String message) { + super(message); + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/ByteBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/ByteBuffer.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,1020 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import java.io.*; +import nsk.share.*; + +/** + * This class represents a byte buffer of variable size. + */ +public class ByteBuffer { + + /** + * Empty byte value (zero). + */ + private static final byte EMPTY_BYTE = (byte)0; + + /** + * Current number of bytes in the buffer. + */ + private int CurrentSize; + + /** + * Delta to increase buffer size. + */ + private int Delta; + + /** + * Current offset from the buffer begin during parsing packet. + */ + int parseOffset; + + /** + * Array of bytes in the buffer. + */ + protected byte[] bytes; + + /** + * Make an empty ByteBuffer object. + */ + public ByteBuffer() { + this(128, 128); + } + + /** + * Make an empty ByteBuffer object with given initial capacity. + * When there is no space for a new byte in a buffer it's capacity + * grows by Delta. + */ + public ByteBuffer(int InitialSize, int Delta) { + if (Delta <= 0) + Delta = 16; + this.Delta = Delta; + CurrentSize = 0; + bytes = new byte[InitialSize]; + parseOffset = 0; + } + + /** + * Make a copy of specified byte buffer. + */ + public ByteBuffer(ByteBuffer buffer) { + int InitialSize = buffer.bytes.length; + Delta = buffer.Delta; + CurrentSize = buffer.CurrentSize; + bytes = new byte[InitialSize]; + for (int i = 0; i < CurrentSize; i++ ) { + bytes[i] = buffer.bytes[i]; + } + parseOffset = 0; + } + + /** + * Return number of bytes in this buffer. + */ + public int length() { + return CurrentSize; + } + + /** + * Return array of bytes in this buffer. + */ + public byte[] getBytes() { + return bytes; + } + + ////////////////////////////////////////////////////////////////////////// + + /** + * Replace the byte at the specified offset in this buffer with the + * less significant byte from the int value. + * + * @throws BoundException if specified offset is out of buffer bounds + */ + public void putByte(int off, byte value) throws BoundException { + + if ((off < 0) || (off >= CurrentSize)) + throw new BoundException("Unable to put one byte at " + offsetString(off)); + + bytes[off] = value; + } + + /** + * Replace len bytes starting at offset off with the bytes from the + * given byte array. + * + * @throws BoundException if offset and length are out of buffer bounds + */ + public void putBytes(int off, byte[] value, int start, int len) throws BoundException { + if (len > (CurrentSize - off)) { + throw new BoundException("Unable to put " + len + " bytes at " + offsetString(off) + + " (available bytes: " + (CurrentSize - off) + ")" ); + } + try { + for (int i = 0; i < len; i++) + putByte(off++, value[start++]); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + len + + "bytes at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Replace count (1 - 8) bytes starting at offset off with the less + * significant bytes from the specified ID value. + * + * @throws BoundException if offset and count are out of buffer bounds + */ + public void putID(int off, long value, int count) throws BoundException { + + if ((count <= 0) || (count > 8)) + throw new TestBug("Illegal number of bytes of ID value to put: " + count); + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of ID value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + putValueBytes(off, value, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of ID value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Replace four bytes starting at offset off with the bytes from the + * specified int value. + * + * @throws BoundException if offset is out of buffer bounds + */ + public void putInt(int off, int value) throws BoundException { + final int count = JDWP.TypeSize.INT; + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of int value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + putValueBytes(off, value, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of int value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Replace two bytes starting at offset off with the bytes + * from the specified short value. + * + * @throws BoundException if offset is out of buffer bounds + */ + public void putShort(int off, short value) throws BoundException { + final int count = JDWP.TypeSize.SHORT; + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of short value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + putValueBytes(off, value, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of short value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Replace eight bytes starting at offset off with the bytes + * from the specified long value. + * + * @throws BoundException if offset is out of buffer bounds + */ + public void putLong(int off, long value) throws BoundException { + final int count = JDWP.TypeSize.LONG; + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of long value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + putValueBytes(off, value, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of long value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Replace four bytes starting at offset off with the bytes + * from the specified float value. + * + * @throws BoundException if offset is out of buffer bounds + */ + public void putFloat(int off, float value) throws BoundException { + final int count = JDWP.TypeSize.FLOAT; + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of float value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + long l = Float.floatToIntBits(value); + putValueBytes(off, l, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of float value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Replace eight bytes starting at offset off with the bytes + * from the specified double value. + * + * @throws BoundException if offset is out of buffer bounds + */ + public void putDouble(int off, double value) throws BoundException { + final int count = JDWP.TypeSize.DOUBLE; + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of double value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + long l = Double.doubleToLongBits(value); + putValueBytes(off, l, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of double value at " + offsetString(off) + ": \n\t" + e); + } + } + + /** + * Replace two bytes starting at offset off with the bytes + * from the specified char value. + * + * @throws BoundException if offset is out of buffer bounds + */ + public void putChar(int off, char value) throws BoundException { + final int count = JDWP.TypeSize.CHAR; + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of char value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + long l = (long)value; + putValueBytes(off, l, count); + } catch (BoundException e) { + throw new Failure("Caught unexpected bound exception while putting " + count + + "bytes of char value at " + offsetString(off) + ":\n\t" + e); + } + } + + ////////////////////////////////////////////////////////////////////////// + + /** + * Append the specified byte to the end of this buffer. + */ + public void addByte(byte value) { + checkSpace(1); + + int where = CurrentSize; + CurrentSize++; + + try { + putByte(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding one byte:\n\t" + + e); + }; + } + + /** + * Append specified byte value repeated count to the end of this buffer. + */ + public void addBytes(byte value, int count) { + checkSpace(count); + for (int i = 0; i < count; i++) { + addByte(value); + } + } + + /** + * Append the bytes from the specified byte array to the end of this buffer. + */ + public void addBytes(byte[] value, int start, int len) { + checkSpace(len); + + int where = CurrentSize; + CurrentSize = CurrentSize + len; + + try { + putBytes(where, value, start, len); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + len + " bytes:\n\t" + e); + }; + } + + /** + * Appends the count (1 - 8) less significant bytes from the + * specified ID value to the end of this buffer. + */ + public void addID(long value, int count) { + if ((count <= 0) || (count > 8)) + throw new TestBug("Illegal number bytes of ID value to add: " + count); + + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + + try { + putID(where, value, count); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of ID value:\n\t" + e); + }; + } + + /** + * Append four bytes from the specified int value to the + * end of this buffer. + */ + public void addInt(int value) { + final int count = JDWP.TypeSize.INT; + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + + try { + putInt(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of int value:\n\t" + e); + }; + } + + /** + * Append two bytes from the specified int value to the + * end of this buffer. + */ + public void addShort(short value) { + final int count = JDWP.TypeSize.SHORT; + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + try { + putShort(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of short value:\n\t" + e); + }; + } + + /** + * Appends eight bytes from the specified long + * value to the end of this buffer. + */ + public void addLong(long value) { + final int count = JDWP.TypeSize.LONG; + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + try { + putLong(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of long value:\n\t" + e); + }; + } + + /** + * Appends four bytes from the specified float + * value to the end of this buffer. + */ + public void addFloat(float value) { + final int count = JDWP.TypeSize.FLOAT; + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + try { + putFloat(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of float value:\n\t" + e); + }; + } + + /** + * Appends eight bytes from the specified double + * value to the end of this buffer. + */ + public void addDouble(double value) { + final int count = JDWP.TypeSize.DOUBLE; + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + try { + putDouble(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of double value:\n\t" + e); + }; + } + + /** + * Appends four bytes from the specified char + * value to the end of this buffer. + */ + public void addChar(char value) { + final int count = JDWP.TypeSize.CHAR; + final int where = CurrentSize; + addBytes(EMPTY_BYTE, count); + try { + putChar(where, value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while adding " + + count + " bytes of float value:\n\t" + e); + }; + } + + ////////////////////////////////////////////////////////////////////////// + + /** + * Read a byte value from this buffer at the specified position. + * + * @throws BoundException if there are no bytes at this position + */ + public byte getByte(int off) throws BoundException { + if (off < 0 || off >= CurrentSize) { + throw new BoundException("Unable to get one byte at " + offsetString(off) + + ": no bytes available"); + } + return bytes[off]; + } + + /** + * Read count bytes (1-8) from this buffer at the specified + * position and returns a long value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public long getID(int off, int count) throws BoundException { + if ((count <= 0) || (count > 8)) + throw new TestBug("Illegal number of bytes of ID value to get: " + count); + + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of ID value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + return getValueBytes(off, count); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of ID value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Read four bytes from this buffer at the specified + * position and returns an integer value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public int getInt(int off) throws BoundException { + final int count = JDWP.TypeSize.INT; + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of int value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + return (int)getValueBytes(off, count); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of int value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Read two bytes from this buffer at the specified + * position and returns a short value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public short getShort(int off) throws BoundException { + final int count = JDWP.TypeSize.SHORT; + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of short value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + return (short)getValueBytes(off, count); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of short value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Read eight bytes from this buffer at the specified + * position and returns a long value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public long getLong(int off) throws BoundException { + final int count = JDWP.TypeSize.LONG; + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of long value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + return getValueBytes(off, count); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of long value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Read eight bytes from this buffer at the specified + * position and returns a double value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public double getDouble(int off) throws BoundException { + final int count = JDWP.TypeSize.DOUBLE; + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of double value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + long value = getValueBytes(off, count); + return Double.longBitsToDouble(value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of long value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Read four bytes from this buffer at the specified + * position and returns a float value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public float getFloat(int off) throws BoundException { + final int count = JDWP.TypeSize.FLOAT; + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of float value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + int value = (int)getValueBytes(off, count); + return Float.intBitsToFloat(value); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of float value at " + offsetString(off) + ":\n\t" + e); + } + } + + /** + * Read two bytes from this buffer at the specified + * position and returns a char value composed of these bytes. + * + * @throws BoundException if there are no so many bytes at this position + */ + public char getChar(int off) throws BoundException { + final int count = JDWP.TypeSize.CHAR; + if (count > CurrentSize - off) { + throw new BoundException("Unable to get " + count + " bytes of char value at " + + offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + try { + int value = (int)getValueBytes(off, count); + return (char)value; + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of char value at " + offsetString(off) + ":\n\t" + e); + } + } + + ////////////////////////////////////////////////////////////////////////// + + /** + * Set the current parser position to 0. + */ + public void resetPosition() { + resetPosition(0); + } + + /** + * Set the current parser position to the specified value. + */ + public void resetPosition(int i) { + parseOffset = i; + } + + /** + * Return current parser position. + */ + public int currentPosition() { + return parseOffset; + } + + /** + * Return true if the parser pointer is set to the end of buffer. + */ + public boolean isParsed() { + return (parseOffset == CurrentSize); + } + + /** + * Read a byte value from this buffer at the current parser position. + * + * @throws BoundException if there are no more bytes in the buffer + */ + public byte getByte() throws BoundException { + return getByte(parseOffset++); + } + + /** + * Read count bytes (1-8) from this buffer at the current parser + * position and returns a long value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public long getID(int count) throws BoundException { + long value = getID(parseOffset, count); + parseOffset += count; + return value; + } + + /** + * Read four bytes from this buffer at the current parser + * position and returns an integer value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public int getInt() throws BoundException { + final int count = JDWP.TypeSize.INT; + int value = getInt(parseOffset); + parseOffset += count; + return value; + } + + /** + * Read two bytes from this buffer at the current parser + * position and returns a short value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public short getShort() throws BoundException { + final int count = JDWP.TypeSize.SHORT; + short value = getShort(parseOffset); + parseOffset += count; + return value; + } + + /** + * Read eight bytes from this buffer at the current parser + * position and returns a long value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public long getLong() throws BoundException { + final int count = JDWP.TypeSize.LONG; + long value = getLong(parseOffset); + parseOffset += count; + return value; + } + + /** + * Read eight bytes from this buffer at the current parser + * position and returns a double value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public double getDouble() throws BoundException { + final int count = JDWP.TypeSize.DOUBLE; + double value = getDouble(parseOffset); + parseOffset += count; + return value; + } + + /** + * Read four bytes from this buffer at the current parser + * position and returns a float value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public float getFloat() throws BoundException { + final int count = JDWP.TypeSize.FLOAT; + float value = getFloat(parseOffset); + parseOffset += count; + return value; + } + + /** + * Read two bytes from this buffer at the current parser + * position and returns a char value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public char getChar() throws BoundException { + final int count = JDWP.TypeSize.CHAR; + char value = getChar(parseOffset); + parseOffset += count; + return value; + } + + /** + * Remove at least first count bytes from the buffer. + */ + + public void deleteBytes(int count) { + int j = 0; + while (count < CurrentSize) + bytes[j++] = bytes[count++]; + + CurrentSize = j; + } + + /** + * Clear the buffer. + */ + public void resetBuffer() { + CurrentSize = 0; + } + + /** + * Return string representation of the buffer starting at given offset. + */ + public String toString(int start) { + + String Result = "", HexLine = "", DisplayLine = ""; + + int j = 0; + + for (int i = start; i < length(); i++) { + + HexLine = HexLine + toHexString(bytes[i], 2) + " "; + + String ch = "."; + if (bytes[i] >= 0x20 && bytes[i] < 0x80) { + try { + ch = new String(bytes, i, 1, "US-ASCII"); + } catch (UnsupportedEncodingException ignore) { + } + } + DisplayLine = DisplayLine + ch; + + if ((i == length() - 1) || (((i - start) & 0x0F) == 0x0F)) { + Result = Result + + " " + + toHexString(j, 4) + ": " + + PadR(HexLine, 48) + " " + + DisplayLine + "\n"; + HexLine = ""; + DisplayLine = ""; + j = j + 16; + } + } + return Result; + } + + /** + * Return string representation of the buffer. + */ + public String toString() { + return toString(0); + } + + /** + * Return string with hexadecimal representation of bytes. + */ + public static String toHexString(long b, int length) { + return Right(Long.toHexString(b), length).replace(' ', '0'); + } + + /** + * Return string with hexadecimal representation of bytes. + */ + public static String toHexDecString(long b, int length) { + return toHexString(b, length) + " (" + b + ")"; + } + + // ----- + + /** + * Return string with hexadecimal representation of offset. + */ + public static String offsetString(int off) { + return "0x" + toHexString(off, 4); + } + + /** + * Return string with hexadecimal representation of the current offset. + */ + public String offsetString() { + return offsetString(currentPosition()); + } + + // ----- + + /** + * Check if there space for new bytes in the buffer. + */ + protected void checkSpace(int space) { + + int newSize = CurrentSize + space; + + if (bytes.length >= newSize) + return; + + byte[] newBytes = new byte[newSize]; + + for (int i = 0; i < CurrentSize; i++) + newBytes[i] = bytes[i]; + + bytes = newBytes; + } + + /** + * Replace count (1 - 8) bytes starting at offset off with the less + * significant bytes from the specified long value. + * + * @throws BoundException if offset and count are out of buffer bounds + */ + protected void putValueBytes(int off, long value, int count) throws BoundException { + if ((count <= 0) || (count > 8)) + throw new TestBug("Illegal number of bytes of value to put: " + count); + + if (count > CurrentSize - off) { + throw new BoundException("Unable to put " + count + " bytes of value at " + + off + " (available bytes: " + (CurrentSize - off) + ")" ); + } + + int shift = (count - 1) * 8; + for (int i = 0; i < count; i++) { + putByte(off++, (byte) ((value >>> shift) & 0xFF)); + shift = shift - 8; + } + } + /** + * Appends the count (1 - 8) less significant bytes from the + * specified long value to the end of this buffer. + */ + protected void addValueBytes(long value, int count) throws BoundException { + if ((count <= 0) || (count > 8)) + throw new TestBug("Illegal number of bytes of value to add: " + count); + + checkSpace(count); + + int where = CurrentSize; + CurrentSize += count; + + putValueBytes(where, value, count); + } + + /** + * Read count bytes (1-8) from this buffer at the specified + * position and returns a long value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ + public long getValueBytes(int off, int count) throws BoundException { + if ((count <= 0) || (count > 8)) + throw new TestBug("Illegal number of bytes of value to get: " + count); + + long l = 0; + + for (int i = 0; i < count; i++) { + l = (l * 0x100) + ((long) getByte(off + i) & 0xFF); + } + + return l; + } + + /** + * Read count bytes (1-8) from this buffer at the current parser + * position and returns a long value composed of these bytes. + * + * @throws BoundException if there are no so many bytes in the buffer + */ +/* + protected long getValueBytes(int count) throws BoundException { + long value = getValueBytes(parseOffset); + parseOffset += count; + return value; + } + */ + + // --- + + private static String PadL(String source, int length, String what) { + + if (length <= 0) + return ""; + + if (source.length() > length) + return PadL("", length, "*"); + + while (source.length() < length) + source = what + source; + + return source; + } + + + private static String PadL(String source, int length) { + return PadL(source, length, " "); + } + + private static String PadR(String source, int length, String what) { + + if (length <= 0) + return ""; + + if (source.length() > length) + return PadR("", length, "*"); + + while (source.length() < length) + source = source + what; + + return source; + } + + private static String PadR(String source, int length) { + return PadR(source, length, " "); + } + + private static String Left(String source, int length) { + + if (length <= 0) + return ""; + + if (length <= source.length()) + return source.substring(0, length); + else + return PadR(source, length); + } + + private static String Right(String source, int length) { + + if (length <= 0) + return ""; + + if (length <= source.length()) + return source.substring(source.length() - length, source.length()); + else + return PadL(source, length); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/CommandPacket.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/CommandPacket.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; + +/** + * This class represents a JDWP command packet. + */ +public class CommandPacket extends Packet { + + /** + * Static counter for enumeration of the command packets. + */ + private static int nextID = 1; + + /** + * Return next free number for enumeration of the command packets. + */ + public static int getLastID() { + return (nextID - 1); + } + + /** + * Make JDWP command packet for specified command. + */ + public CommandPacket(int fullCommand) { + super(); + + setPacketID(nextID++); + setFlags(JDWP.Flag.NONE); + setFullCommand(fullCommand); + } + + /** + * Make JDWP command packet for specified command. + */ + public CommandPacket(int fullCommand, int id) { + super(); + + setPacketID(id); + setFlags(JDWP.Flag.NONE); + setFullCommand(fullCommand); + } + + /** + * Make command packet with data from the specified byte buffer. + */ +// public CommandPacket(ByteBuffer packet) { + public CommandPacket(Packet packet) { + super(packet); + } + + /** + * Return full command number for this packet. + */ + public int getFullCommand() { + int id = 0; + + try { + id = (int) getID(FullCommandOffset, 2); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting command number from header:\n\t" + + e); + } + + return id; + } + + /** + * Return short command number for this packet. + */ + public byte getCommand() { + byte id = 0; + + try { + id = getByte(CommandOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting command number from header:\n\t" + + e); + } + + return id; + } + + /** + * Return command set number for this packet. + */ + public byte getCommandSet() { + byte id = 0; + + try { + id = getByte(CommandSetOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting command number from header:\n\t" + + e); + } + + return id; + } + + /** + * Assign command number for this packet. + */ + public void setFullCommand(int fullCommand) { + try { + putID(FullCommandOffset, fullCommand, 2); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while setting command number into header: " + + e); + } + } + + /** + * Return string representation of the command packet header. + */ + public String headerToString() { + return super.headerToString() + + " " + toHexString(CommandSetOffset, 4) + " (cmd set): 0x" + toHexDecString(getCommandSet(), 2) + "\n" + + " " + toHexString(CommandOffset, 4) + " (command): 0x" + toHexDecString(getCommand(), 2) + "\n"; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,1659 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; +import nsk.share.jpda.*; + +import java.util.*; +import java.io.*; + +/** + * This class is used to interact with debugee VM using JDWP features. + *

+ * This class is an mirror of debugee VM that is constructed by + * Binder and uses Transport object + * to interact with debugee VM. + *

+ * In addition to the general abities to control of debugee VM process, + * provided by the base class DebugeeProcess, this class + * adds some service methods that uses JDWP protocol to simplify interaction + * with debugee VM (such as finding classes, setting breakpoints, + * handling events, and so on.). + * + * @see Binder + * @see Transport + * @see DebugeeProcess + */ +abstract public class Debugee extends DebugeeProcess { + + /** Binder that creates this debugee. */ + protected Binder binder = null; + + protected LinkedList eventQueue = new LinkedList(); + + protected Transport transport = null; + + /** Make new Debugee object for the given binder. */ + protected Debugee (Binder binder) { + super(binder); + this.argumentHandler = binder.getArgumentHandler(); + this.binder = binder; + prefix = "Debugee> "; + } + + /** Return Binder of the debugee object. */ + public Binder getBinder() { + return binder; + } + + /** Return Transport of the debugee object. */ + public Transport getTransport() { + return transport; + } + + /** + * Prepare transport object for establishing connection. + * This may change connection options in argumentHandler. + * + * @return specific address string if listening has started or null otherwise + */ + public String prepareTransport(ArgumentHandler argumentHandler) { + String address = null; + try { + if (argumentHandler.isSocketTransport()) { + SocketTransport socket_transport = new SocketTransport(log); + if (argumentHandler.isListeningConnector()) { + int port = 0; + if (argumentHandler.isTransportAddressDynamic()) { + port = socket_transport.bind(0); +// argumentHandler.setTransportPortNumber(port); + } else { + port = argumentHandler.getTransportPortNumber(); + socket_transport.bind(port); + } + address = argumentHandler.getTestHost() + ":" + port; + } + transport = socket_transport; +/* + } else if (argumentHandler.isShmemTransport()) { + ShmemTransport shmem_transport = new ShmemTransport(log); + if (argumentHandler.isListeningConnector()) { + String sharedName = agrHandler.getTransportSharedName(); + shmem_transport.bind(sharedName); + address = sharedName; + } + transport = shmem_transport; + */ + } else { + throw new TestBug("Unexpected transport type: " + + argumentHandler.getTransportType()); + } + + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught IOException while preparing for JDWP transport connection:\n\t" + + e); + } + + return address; + } + + /** + * Establish connection to debugee VM. + */ + public Transport connect() { + if (transport == null) { + throw new Failure("Attemt to establish JDWP connection for not prepared transport"); + } + + try { + if (argumentHandler.isSocketTransport()) { + display("Establishing JDWP socket connection"); + SocketTransport socket_transport = (SocketTransport)transport; + int transportPort = argumentHandler.getTransportPortNumber(); + if (argumentHandler.isAttachingConnector()) { + String debugeeHost = argumentHandler.getDebugeeHost(); + display("Attaching to debugee: " + debugeeHost + ":" + transportPort); + socket_transport.attach(debugeeHost, transportPort); + } else if (argumentHandler.isListeningConnector()) { + display("Listening from debugee"); + socket_transport.accept(); + } else { + throw new TestBug("Unexpected connector type: " + + argumentHandler.getConnectorType()); + } +/* + } else if (argumentHandler.isShmemTransport()) { + display("Establishing JDWP shared-memory connection"); + ShmemTransport shmem_transport = (ShmemTransport)transport; + String sharedName = argumentHandler.getTransportSharedName(); + if (argumentHandler.isAttachingConnector()) { + display("Attaching to debugee: " + sharedName); + shmem_transport.attach(sharedName); + } else if (argumentHandler.isListeningConnector()) { + display("Listening from debugee"); + shmem_transport.accept(); + } else { + throw new TestBug("Unexpected connector type: " + + argumentHandler.getConnectorType()); + } + */ + } else { + throw new TestBug("Unexpected transport type: " + + argumentHandler.getTransportType()); + } + + transport.handshake(); + + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught IOException while establishing JDWP transport connection:\n\t" + + e); + } + return transport; + } + + // --------------------------------------------------- // + + /** + * Waits for VM_INIT event from debugee VM. + */ + public void waitForVMInit() { + String eventName = "VirtualMachine.VM_START"; + EventPacket packet = receiveEventFor(JDWP.EventKind.VM_START, eventName); +// String versionInfo = getVersionInfo(); +// display("Target VM started:\n" + versionInfo); + } + + /** + * Waits for VM_DEATH event from debugee VM. + */ + public void waitForVMDeath() { + String eventName = "VirtualMachine.VM_DEATH"; + EventPacket packet = receiveEventFor(JDWP.EventKind.VM_DEATH, eventName); + } + + /** + * Wait for class loaded on debugee start up and return its classID. + * Debuggee should be initially suspended and it will also left suspended + * by the CLASS_PREPARE event request. + */ + public long waitForClassLoaded(String className, byte suspendPolicy) { + // make request for CLASS_PREPARE_EVENT for this class name + int requestID = requestClassPrepareEvent(className, suspendPolicy); + // resume initially suspended debugee + resume(); + // wait for CLASS_PREPARE_EVENT + return waitForClassPrepareEvent(requestID, className); + } + + /** + * Wait for classes loaded on debugee start up and return their classIDs. + * Debuggee should be initially suspended and it will also left suspended + * by the CLASS_PREPARE event request. + */ + public long[] waitForClassesLoaded(String classNames[], byte suspendPolicy) { + int count = classNames.length; + + // make requests for CLASS_PREPARE_EVENT for these class names + int[] requestIDs = new int[count]; + for (int i = 0; i < count; i++) { + requestIDs[i] = requestClassPrepareEvent(classNames[i], suspendPolicy); + } + + // resume initially suspended debugee + resume(); + + return waitForClassPrepareEvents(requestIDs, classNames); + } + + /** + * Wait for breakpoint reached and return threadIDs. + * Debuggee should be initially suspended and it will also left suspended + * by the BREAKPOINT event request. + */ + public long waitForBreakpointReached(long classID, String methodName, + int line, byte suspendPolicy) { + // query debuggee for methodID + long methodID = getMethodID(classID, methodName, true); + // create BREAKPOINT event request + int requestID = requestBreakpointEvent(JDWP.TypeTag.CLASS, classID, methodID, + line, suspendPolicy); + // resume initially suspended debugee + resume(); + // wait for BREAKPOINT event + return waitForBreakpointEvent(requestID); + } + + // --------------------------------------------------- // + + /** + * Wait for CLASS_PREPARE event made by given request received + * and return classID. + * Debuggee will be left suspended by the CLASS_PREPARE event. + */ + public long waitForClassPrepareEvent(int requestID, String className) { + String error = "Error occured while waiting for CLASS_PREPARE event for class:\n\t" + + className; + + String signature = "L" + className.replace('.', '/') + ";"; + long classID = 0; + + // wait for CLASS_PREPARE event + for(;;) { + EventPacket event = receiveEvent(); + byte eventSuspendPolicy = 0; + long eventThreadID = 0; + try { + eventSuspendPolicy = event.getByte(); + int events = event.getInt(); + for (int i = 0; i < events; i++) { + // check event kind + byte eventKind = event.getByte(); + if (eventKind == JDWP.EventKind.VM_DEATH) { + complain("Unexpected VM_DEATH event received: " + eventKind + + " (expected: " + JDWP.EventKind.CLASS_PREPARE +")"); + throw new Failure(error); + } else if (eventKind != JDWP.EventKind.CLASS_PREPARE) { + complain("Unexpected event kind received: " + eventKind + + " (expected: " + JDWP.EventKind.CLASS_PREPARE +")"); + throw new Failure(error); + } + + // extract CLASS_PREPARE event specific data + int eventRequestID = event.getInt(); + eventThreadID = event.getObjectID(); + byte eventRefTypeTag = event.getByte(); + long eventClassID = event.getReferenceTypeID(); + String eventClassSignature = event.getString(); + int eventClassStatus = event.getInt(); + + // check if event was single + if (events > 1) { + complain("Not single CLASS_PREPARE event received for class:\n\t" + + eventClassSignature); + throw new Failure(error); + } + + // check if event is for expected class + if (eventClassSignature.equals(signature)) { + + // check if event is because of expected request + if (eventRequestID != requestID) { + complain("CLASS_PREPARE event with unexpected requestID (" + + eventRequestID + ") received for class:\n\t" + + eventClassSignature); + throw new Failure(error); + } + + // remove event request + clearEventRequest(JDWP.EventKind.CLASS_PREPARE, requestID); + + return eventClassID; + } else { + complain("Unexpected CLASS_PREPARE event received with class signature:\n" + + " " + eventClassSignature); + } + + } + + } catch (BoundException e) { + complain("Unable to extract data from event packet while waiting for CLASS_PREPARE event:\n\t" + + e.getMessage() + "\n" + event); + throw new Failure(error); + } + + // resume debuggee according to event suspend policy + resumeEvent(eventSuspendPolicy, eventThreadID); + } + } + + /** + * Wait for CLASS_PREPARE events made by given requests received + * and return classIDs. + * Debuggee will be left suspended by the CLASS_PREPARE event. + */ + public long[] waitForClassPrepareEvents(int requestIDs[], String classNames[]) { + int count = classNames.length; + String error = "Error occured while waiting for " + count + " CLASS_PREPARE events"; + + // prepare expected class signatures + String[] signatures = new String[count]; + for (int i = 0; i < count; i++) { + signatures[i] = "L" + classNames[i].replace('.', '/') + ";"; + } + + // clear list of classIDs + long[] classIDs = new long[count]; + for (int i = 0; i < count; i++) { + classIDs[i] = 0; + } + + // wait for all expected CLASS_PREPARE events + int received = 0; + for(;;) { + EventPacket event = receiveEvent(); + byte eventSuspendPolicy = 0; + long eventThreadID = 0; + try { + eventSuspendPolicy = event.getByte(); + int events = event.getInt(); + for (int i = 0; i < events; i++) { + // check event kind + byte eventKind = event.getByte(); + if (eventKind == JDWP.EventKind.VM_DEATH) { + complain("Unexpected VM_DEATH event received: " + eventKind + + " (expected: " + JDWP.EventKind.CLASS_PREPARE +")"); + throw new Failure(error); + } else if (eventKind != JDWP.EventKind.CLASS_PREPARE) { + complain("Unexpected event kind received: " + eventKind + + " (expected: " + JDWP.EventKind.CLASS_PREPARE +")"); + throw new Failure(error); + } + + // extracy CLASS_PREPARE event specific data + int eventRequestID = event.getInt(); + eventThreadID = event.getObjectID(); + byte eventRefTypeTag = event.getByte(); + long eventClassID = event.getReferenceTypeID(); + String eventClassSignature = event.getString(); + int eventClassStatus = event.getInt(); + + // check if event was single + if (events > 1) { + complain("Not single CLASS_PREPARE event received for class:\n\t" + + eventClassSignature); + } + + // find appropriate class by signature + boolean found = false; + for (int j = 0; j < count; j++) { + if (eventClassSignature.equals(signatures[j])) { + found = true; + + // check if event is not duplicated + if (classIDs[j] != 0) { + complain("Extra CLASS_PREPARE event recieved for class:\n\t" + + eventClassSignature); + } else { + classIDs[j] = eventClassID; + received ++; + } + + // check if event is because of expected request + if (eventRequestID != requestIDs[j]) { + complain("CLASS_PREPARE event with unexpected requestID (" + + requestIDs[j] + ") received for class:\n\t" + + eventClassSignature); + } else { + clearEventRequest(JDWP.EventKind.CLASS_PREPARE, requestIDs[j]); + } + } + } + if (!found) { + log.complain("Unexpected CLASS_PREPARE event received with class signature:\n" + + " " + eventClassSignature); + } + } + } catch (BoundException e) { + complain("Unable to extract data from event packet while waiting for CLASS_PREPARE event:\n\t" + + e.getMessage() + "\n" + event); + throw new Failure(error); + } + + // if all events received return without resuming + if (received >= count) + return classIDs; + + // resume debuggee according to events suspend policy + resumeEvent(eventSuspendPolicy, eventThreadID); + } + } + + /** + * Wait for BREAKPOINT event made by the given request and return threadID. + * Debuggee will be left suspended by the BREAKPOINT event. + */ + public long waitForBreakpointEvent(int requestID) { + String error = "Error occured while waiting for BREAKPOINT event for "; + + for(;;) { + EventPacket event = receiveEvent(); + byte eventSuspendPolicy = 0; + long eventThreadID = 0; + try { + eventSuspendPolicy = event.getByte(); + int events = event.getInt(); + for (int i = 0; i < events; i++) { + // check event kind + byte eventKind = event.getByte(); + if (eventKind == JDWP.EventKind.VM_DEATH) { + complain("Unexpected VM_DEATH event received: " + eventKind + + " (expected: " + JDWP.EventKind.BREAKPOINT +")"); + throw new Failure(error); + } else if (eventKind != JDWP.EventKind.BREAKPOINT) { + complain("Unexpected event kind received: " + eventKind + + " (expected: " + JDWP.EventKind.BREAKPOINT +")"); + throw new Failure(error); + } + + // extrack specific BREAKPOINT event data + int eventRequestID = event.getInt(); + eventThreadID = event.getObjectID(); + JDWP.Location eventLocation = event.getLocation(); + + if (eventRequestID == requestID) { + clearEventRequest(JDWP.EventKind.BREAKPOINT, requestID); + return eventThreadID; + } else { + complain("Unexpected BREAKPOINT event received with requestID: " + + eventRequestID + " (expected: " + requestID + ")"); + } + } + } catch (BoundException e) { + complain("Unable to extract data from event packet while waiting for BREAKPOINT event:\n\t" + + e.getMessage() + "\n" + event); + throw new Failure(error); + } + + resumeEvent(eventSuspendPolicy, eventThreadID); + } + } + + /** + * Resume debuggee according given event suspend policy. + */ + public void resumeEvent(byte suspendPolicy, long threadID) { + if (suspendPolicy == JDWP.SuspendPolicy.NONE) { + // do nothing + } else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { + resumeThread(threadID); + } else if (suspendPolicy == JDWP.SuspendPolicy.ALL) { + resume(); + } else { + throw new Failure("Unexpected event suspend policy while resuming debuggee: " + + suspendPolicy); + } + } + + // --------------------------------------------------- // + + /** + * Query target VM for version info. + */ + public String getVersionInfo() { + String commandName = "VirtualMachine.Version"; + CommandPacket command = + new CommandPacket(JDWP.Command.VirtualMachine.Version); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + String description = reply.getString(); + int jdwpMajor = reply.getInt(); + int jdwpMinor = reply.getInt(); + String vmVersion = reply.getString(); + String vmName = reply.getString(); + return description; + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting JDWP and VM version info"); + } + } + + /** + * Query target VM about VM dependent ID sizes. + */ + public void queryForIDSizes() { + String commandName = "VirtualMachine.IDSizes"; + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.IDSizes); + ReplyPacket reply = receiveReplyFor(command); + try { + reply.resetPosition(); + JDWP.TypeSize.FIELD_ID = reply.getInt(); + JDWP.TypeSize.METHOD_ID = reply.getInt(); + JDWP.TypeSize.OBJECT_ID = reply.getInt(); + JDWP.TypeSize.REFERENCE_TYPE_ID = reply.getInt(); + JDWP.TypeSize.FRAME_ID = reply.getInt(); + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting VM dependent ID sizes"); + } + JDWP.TypeSize.CalculateSizes(); + } + + // --------------------------------------------------- // + + /** + * Suspend the debugee VM by sending VirtualMachine.Suspend command. + */ + public void suspend() { + String commandName = "VirtualMachine.Suspend"; + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Suspend); + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + /** + * Resume the debugee VM by sending VirtualMachine.Resume command. + */ + public void resume() { + String commandName = "VirtualMachine.Resume"; + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Resume); + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + /** + * Dispose the debugee VM by sending VirtualMachine.Dispose command. + */ + public void dispose() { + String commandName = "VirtualMachine.Dispose"; + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Dispose); + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + // --------------------------------------------------- // + + /** + * Sends JDWP command packet. + */ + public void sendCommand(CommandPacket packet, String commandName) { + try { + transport.write(packet); + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + complain("Caught IOException while sending command packet for " + + commandName + ":\n\t" + e); + display("Command packet:\n" + packet); + throw new Failure("Error occured while sending command: " + commandName); + } + } + + /** + * Receive next JDWP packet. + */ +/* + public Packet receivePacket() { + try { + ReplyPacket packet = new ReplyPacket(); + transport.read(packet); + return packet; + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught IOException while receiving reply packet:\n\t" + e); + } + } + */ + /** + * Receive next JDWP reply packet. + */ + public ReplyPacket receiveReply() { + try { + for (;;) { + Packet packet = new Packet(); + transport.read(packet); + + if (packet.getFlags() == JDWP.Flag.REPLY_PACKET) { + ReplyPacket reply = new ReplyPacket(packet); + return reply; + } + + EventPacket event = new EventPacket(packet); + display("Placing received event packet into queue"); + eventQueue.add(event); + } + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught IOException while receiving reply packet:\n\t" + e); + } + } + + /** + * Get next JDWP event packet by reading from transport or getting stored + * event in the event queue. + */ + public EventPacket getEventPacket() throws IOException { + // check events queue first + if (!eventQueue.isEmpty()) { + EventPacket event = (EventPacket)(eventQueue.removeFirst()); + return event; + } + + // read from transport + Packet packet = new Packet(); + transport.read(packet); + + EventPacket event = new EventPacket(packet); + return event; + } + + /** + * Get next JDWP event packet by reading from transport for specified timeout + * or getting stored event in the event queue. + */ + public EventPacket getEventPacket(long timeout) throws IOException { + transport.setReadTimeout(timeout); + return getEventPacket(); + } + + /** + * Receive next JDWP event packet. + */ + public EventPacket receiveEvent() { + EventPacket packet = null; + try { + packet = getEventPacket(); + } catch (IOException e) { + e.printStackTrace(log.getOutStream()); + throw new Failure("Caught IOException while receiving event packet:\n\t" + e); + } + + if (packet.getFlags() == JDWP.Flag.REPLY_PACKET) { + ReplyPacket reply = new ReplyPacket(packet); + log.complain("Unexpected reply packet received with id: " + + reply.getPacketID()); + log.display("Reply packet:\n" + reply); + throw new Failure("Unexpected reply packet received instead of event packet"); + } + + return packet; + } + + /** + * Send specified command packet, receive and check reply packet. + * + * @throws Failure if exception caught in sending and reading packets + */ + public ReplyPacket receiveReplyFor(CommandPacket command) { + return receiveReplyFor(command, Packet.toHexString(command.getCommand(), 4)); + } + + /** + * Send specified command packet, receive and check reply packet. + * + * @throws Failure if exception caught in sending and reading packets + */ + public ReplyPacket receiveReplyFor(CommandPacket command, String commandName) { + ReplyPacket reply = null; + sendCommand(command, commandName); + reply = receiveReply(); + try { + reply.checkHeader(command.getPacketID()); + } catch (BoundException e) { + complain("Wrong header of reply packet for command "+ commandName + ":\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Wrong reply packet received for command: " + commandName); + } + return reply; + } + + /** + * Receive and check event packet for specified event kind. + * + * @throws Failure if exception caught in sending and reading packets + */ + public EventPacket receiveEventFor(int eventKind, String eventName) { + EventPacket event = null; + event = receiveEvent(); + try { + event.checkHeader(eventKind); + } catch (BoundException e) { + complain("Wrong header of event packet for expected "+ eventName + " event:\n\t" + + e.getMessage()); + display("Event packet:\n" + event); + throw new Failure("Wrong event packet received for expected event: " + eventName); + } + return event; + } + + // --------------------------------------------------- // + + /** + * Check common VM capability. + */ + public boolean getCapability(int capability, String name) { + String commandName = "VirtualMachine.Capabilities"; + + int count = JDWP.Capability.CAN_GET_MONITOR_INFO + 1; + if (capability < 0 || capability >= count) { + throw new TestBug("Illegal capability number (" + capability + + ") while checking for VM capability: " + name); + } + + CommandPacket command = + new CommandPacket(JDWP.Command.VirtualMachine.Capabilities); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + reply.resetPosition(); + + for (int i = 0; i < count; i++) { + byte value = reply.getByte(); + if (i == capability) { + return (value != 0); + } + } + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting VM capability: " + + name); + } + + throw new TestBug("Illegal capability number (" + capability + + ") while checking for VM capability: " + name); + } + + /** + * Check new VM capability (since JDWP version 1.4). + */ + public boolean getNewCapability(int capability, String name) { + String commandName = "VirtualMachine.CapabilitiesNew"; + int count = JDWP.Capability.CAN_SET_DEFAULT_STRATUM + 1; + + if (capability < 0 || capability >= count) { + throw new TestBug("Illegal capability number (" + capability + + ") while checking for VM new capability: " + name); + } + + CommandPacket command = + new CommandPacket(JDWP.Command.VirtualMachine.CapabilitiesNew); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + reply.resetPosition(); + + for (int i = 0; i < count; i++) { + byte value = reply.getByte(); + if (i == capability) { + return (value != 0); + } + } + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting VM new capability: " + + name); + } + + throw new TestBug("Illegal capability number (" + capability + + ") while checking for VM new capability: " + name); + } + + // --------------------------------------------------- // + + /** + * Return ReferenceTypeID for requested class by given signature. + */ + public long getReferenceTypeID(String classSignature) { + String commandName = "VirtualMachine.ClassesBySignature"; + CommandPacket command = + new CommandPacket(JDWP.Command.VirtualMachine.ClassesBySignature); + command.addString(classSignature); + command.setLength(); + ReplyPacket reply = receiveReplyFor(command, commandName); + + long typeID = 0; + + try { + reply.resetPosition(); + + int classes = reply.getInt(); + for (int i = 0; i < classes; i++) { + byte refTypeTag = reply.getByte(); + typeID = reply.getReferenceTypeID(); + int status = reply.getInt(); + } + + if (classes < 0) { + throw new Failure("Negative number (" + classes + + ") of referenceTypeIDs received for signature: " + + classSignature); + } + + if (classes == 0) { + throw new Failure("No any referenceTypeID received for signature: " + + classSignature); + } + + if (classes > 1) { + throw new Failure("Too many (" + classes + + ") referenceTypeIDs received for signature: " + + classSignature); + } + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting referenceTypeID for signature: " + + classSignature); + } + + return typeID; + } + + // --------------------------------------------------- // + + + /** + * Get list of IDs of supertypes (interfaces and classes) for given class. + */ + public long[] getSupertypes(long classID, boolean declared) { + Vector vector = new Vector(); + addSupertypes(classID, vector, null, null, false, declared); + return makeListOfLongValues(vector); + } + + /** + * Get list of IDs of superclasses for given class. + */ + public long[] getSuperclasses(long classID, boolean declared) { + Vector vector = new Vector(); + addSupertypes(classID, null, null, vector, false, declared); + return makeListOfLongValues(vector); + } + + /** + * Get list of IDs of implemented interfaces for given class. + */ + public long[] getImplementedInterfaces(long classID, boolean declared) { + Vector vector = new Vector(); + addSupertypes(classID, null, vector, null, false, declared); + return makeListOfLongValues(vector); + } + + /** + * Get list of IDs of superinterfaces for given interface. + */ + public long[] getSuperinterfaces(long interfaceID, boolean declared) { + Vector vector = new Vector(); + addSupertypes(interfaceID, null, vector, null, true, declared); + return makeListOfLongValues(vector); + } + + // --------------------------------------------------- // + + /** + * Get list of IDs of methods of given class. + */ + public long[] getMethodIDs(long classID, boolean declared) { + Vector list = new Vector(); + addMethods(classID, list, null, null, null, false, declared); + return makeListOfLongValues(list); + } + + /** + * Get list of names of methods of given class. + */ + public String[] getMethodNames(long classID, boolean declared) { + Vector list = new Vector(); + addMethods(classID, null, list, null, null, false, declared); + return makeListOfStringValues(list); + } + + /** + * Get list of signatures of methods of given class. + */ + public String[] getMethodSignatures(long classID, boolean declared) { + Vector list = new Vector(); + addMethods(classID, null, null, list, null, false, declared); + return makeListOfStringValues(list); + } + + /** + * Get ID of a method of given class by name. + */ + public long getMethodID(long classID, String name, boolean declared) { + Vector IDs = new Vector(); + Vector names = new Vector(); + addMethods(classID, IDs, names, null, null, false, declared); + int count = names.size(); + for (int i = 0; i < count; i++) { + if (name.equals(names.elementAt(i))) { + return (IDs.elementAt(i)).longValue(); + } + } + throw new Failure("Method \"" + name + "\" not found for classID: " + classID); + } + + // --------------------------------------------------- // + + /** + * Get list of IDs of static fields of given class. + */ + public long[] getClassFieldIDs(long classID, boolean declared) { + Vector list = new Vector(); + addFields(classID, list, null, null, null, false, declared); + return makeListOfLongValues(list); + } + + /** + * Get list of names of static fields of given class. + */ + public String[] getClassFieldNames(long classID, boolean declared) { + Vector list = new Vector(); + addFields(classID, null, list, null, null, false, declared); + return makeListOfStringValues(list); + } + + /** + * Get list of signatures of static fields of given class. + */ + public String[] getClassFieldSignatures(long classID, boolean declared) { + Vector list = new Vector(); + addFields(classID, null, null, list, null, false, declared); + return makeListOfStringValues(list); + } + + /** + * Get ID of a static field of given class by name. + */ + public long getClassFieldID(long classID, String name, boolean declared) { + Vector IDs = new Vector(); + Vector names = new Vector(); + addFields(classID, IDs, names, null, null, false, declared); + int count = names.size(); + for (int i = 0; i < count; i++) { + if (name.equals((String)names.elementAt(i))) { + return ((Long)IDs.elementAt(i)).longValue(); + } + } + throw new Failure("Static field \"" + name + "\" not found for classID: " + classID); + } + + // --------------------------------------------------- // + + /** + * Get value of a static field of given class. + */ + public JDWP.Value getStaticFieldValue(long typeID, long fieldID) { + String commandName = "ReferenceType.GetValues"; + CommandPacket command = + new CommandPacket(JDWP.Command.ReferenceType.GetValues); + command.addReferenceTypeID(typeID); + command.addInt(1); + command.addFieldID(fieldID); + + ReplyPacket reply = receiveReplyFor(command, commandName); + JDWP.Value value = null; + + try { + reply.resetPosition(); + + int count = reply.getInt(); + if (count < 1) { + throw new Failure("No values returned for static fieldID: " + fieldID); + } + value = reply.getValue(); + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName +" command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting value of static field: " + + + fieldID); + } + return value; + } + + /** + * Get value of particular type from a static field of given class. + */ + public JDWP.Value getStaticFieldValue(long typeID, String fieldName, byte tag) { + long fieldID = getClassFieldID(typeID, fieldName, true); + JDWP.Value value = getStaticFieldValue(typeID, fieldID); + + if (value.getTag() != tag) { + complain("unexpedted value tag returned from debuggee: " + value.getTag() + + " (expected: " + tag + ")"); + throw new Failure("Error occured while getting value from static field: " + + fieldName); + } + return value; + } + + /** + * Set value of a static field of given class. + */ + public void setStaticFieldValue(long typeID, long fieldID, JDWP.Value value) { + String commandName = "ClassType.SetValues"; + CommandPacket command = + new CommandPacket(JDWP.Command.ClassType.SetValues); + command.addReferenceTypeID(typeID); + command.addInt(1); + command.addFieldID(fieldID); + command.addUntaggedValue(value, value.getTag()); + + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + /** + * Get value of a field of given object. + */ + public JDWP.Value getObjectFieldValue(long objectID, long fieldID) { + String commandName = "ObjectReference.GetValues"; + CommandPacket command = + new CommandPacket(JDWP.Command.ObjectReference.GetValues); + command.addObjectID(objectID); + command.addInt(1); + command.addFieldID(fieldID); + + ReplyPacket reply = receiveReplyFor(command, commandName); + JDWP.Value value = null; + + try { + reply.resetPosition(); + + int count = reply.getInt(); + if (count < 1) { + throw new Failure("No values returned for object fieldID: " + fieldID); + } + value = reply.getValue(); + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting value of object field: " + + + fieldID); + } + return value; + } + + /** + * Set value of a static field of given class. + */ + public void setObjectFieldValue(long objectID, long fieldID, JDWP.Value value) { + String commandName = "ObjectReference.SetValues"; + CommandPacket command = + new CommandPacket(JDWP.Command.ObjectReference.SetValues); + command.addObjectID(objectID); + command.addInt(1); + command.addFieldID(fieldID); + command.addUntaggedValue(value, value.getTag()); + + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + // --------------------------------------------------- // + + /** + * Find threadID for given thread name among all active threads. + */ + public long getThreadID(String name) { + // request list of all threadIDs + int threads = 0; + long threadIDs[] = null; + { + String commandName = "VirtualMachine.AllThreads"; + CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.AllThreads); + ReplyPacket reply = receiveReplyFor(command, commandName); + reply.resetPosition(); + try { + threads = reply.getInt(); + threadIDs = new long[threads]; + + for (int i = 0; i < threads; i++) { + threadIDs[i] = reply.getObjectID(); + } + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting threadID for thread name: " + + name); + } + } + + // request name for each threadID + for (int i = 0; i < threads; i++) { + String commandName = "ThreadReference.Name"; + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Name); + command.addObjectID(threadIDs[i]); + ReplyPacket reply = receiveReplyFor(command, commandName); + try { + reply.resetPosition(); + String threadName = reply.getString(); + if (threadName.equals(name)) { + return threadIDs[i]; + } + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting name for threadID: " + + threadIDs[i]); + } + } + + throw new Failure("No threadID found for thread name: " + name); + } + + /** + * Return thread name for the given threadID. + */ + public String getThreadName(long threadID) { + String commandName = "ThreadReference.Name"; + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Name); + command.addObjectID(threadID); + ReplyPacket reply = receiveReplyFor(command, commandName); + try { + reply.resetPosition(); + String threadName = reply.getString(); + return threadName; + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting name for threadID: " + + threadID); + } + } + + /** + * Suspend thread for the given threadID. + */ + public void suspendThread(long threadID) { + String commandName = "ThreadReference.Suspend"; + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Suspend); + command.addObjectID(threadID); + + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + /** + * Resume thread for the given threadID. + */ + public void resumeThread(long threadID) { + String commandName = "ThreadReference.resume"; + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Resume); + command.addObjectID(threadID); + + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + /** + * Return frameID for the current frame of the thread. + * Thread must be suspended. + */ + public long getCurrentFrameID(long threadID) { + String commandName = "ThreadReference.Frames"; + CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Frames); + command.addObjectID(threadID); // threadID + command.addInt(0); // startFrame + command.addInt(1); // length + + ReplyPacket reply = receiveReplyFor(command, commandName); + try { + reply.resetPosition(); + int frames = reply.getInt(); + if (frames != 1) { + throw new Failure("Not only one current frame returned for threadID " + + threadID + ": " + frames); + } + long frameID = reply.getFrameID(); + JDWP.Location location = reply.getLocation(); + return frameID; + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting current frame for threadID: " + + threadID); + } + } + + // --------------------------------------------------- // + + /** + * Find line number for the given location from the method line table. + * If approximate is true the found line should begin + * with code index of the given location. Otherwise, the found line will + * just cover code index of the given location. + */ + public int getLineNumber(JDWP.Location location, boolean approximate) { + String commandName = "Method.LineTable"; + CommandPacket command = new CommandPacket(JDWP.Command.Method.LineTable); + command.addReferenceTypeID(location.getClassID()); + command.addMethodID(location.getMethodID()); + long index = location.getIndex(); + ReplyPacket reply = receiveReplyFor(command, commandName); + String msg = "Error occured while getting line number for location: " + location; + try { + reply.resetPosition(); + long start = reply.getLong(); + if (index < start) { + complain("Location index (" + index + + ") is less than start method index (" + start); + throw new Failure(msg); + } + long end = reply.getLong(); + if (index > end) { + complain("Location index (" + index + + ") is greater than end method index (" + end); + throw new Failure(msg); + } + int lines = reply.getInt(); + if (!approximate) { + for (int i = 0; i < lines; i++) { + long lineCodeIndex = reply.getLong(); + int lineNumber = reply.getInt(); + if (lineCodeIndex == index) { + return lineNumber; + } + } + throw new Failure("No exact line number exactly for location: " + location); + } else { + int prevLine = -1; + for (int i = 0; i < lines; i++) { + long lineCodeIndex = reply.getLong(); + int lineNumber = reply.getInt(); + if (lineCodeIndex == index) { + return lineNumber; + } else if (lineCodeIndex > index) { + break; + } + prevLine = lineNumber; + } + if (prevLine < 0) + throw new Failure("No approximate line number found for location: " + location); + return prevLine; + } + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure(msg); + } + } + + /** + * Find line index for the given line number from the method line table. + */ + public long getCodeIndex(long classID, long methodID, int lineNumber) { + String commandName = "Method.LineTable"; + CommandPacket command = new CommandPacket(JDWP.Command.Method.LineTable); + command.addReferenceTypeID(classID); + command.addMethodID(methodID); + ReplyPacket reply = receiveReplyFor(command, commandName); + String msg = "Error occured while getting code index for line number: " + lineNumber; + try { + reply.resetPosition(); + long start = reply.getLong(); + long end = reply.getLong(); + int lines = reply.getInt(); + for (int i = 0; i < lines; i++) { + long lineCodeIndex = reply.getLong(); + int line = reply.getInt(); + if (lineNumber == line) { + return lineCodeIndex; + } + } + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure(msg); + } + + throw new Failure("No code index found for line number: " + lineNumber); + } + + // --------------------------------------------------- // + + /** + * Make the specified event request into debuggee. + */ + public int requestEvent(CommandPacket requestCommand, String name) { + String commandName = "EventRequest.Set"; + ReplyPacket reply = receiveReplyFor(requestCommand, name); + + try { + reply.resetPosition(); + + int requestID = reply.getInt(); + return requestID; + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Request command packet:\n" + requestCommand); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while making event request: " + name); + } + } + + /** + * Remove existing event request from debuggee. + */ + public void clearEventRequest(byte eventKind, int requestID) { + String commandName = "EventRequest.Clear"; + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + command.addByte(eventKind); + command.addInt(requestID); + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + /** + * Make request for CLASS_PREPARE event for specified class into debuggee. + */ + public int requestClassPrepareEvent(String className, byte suspendPolicy) { + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + command.addByte(JDWP.EventKind.CLASS_PREPARE); + command.addByte(suspendPolicy); + command.addInt(1); + command.addByte(JDWP.EventModifierKind.CLASS_MATCH); + command.addString(className); + + return requestEvent(command, "CLASS_PREPARE"); + } + + /** + * Make request for BREAKPOINT event for the specified location into debuggee. + */ + public int requestBreakpointEvent(JDWP.Location location, byte suspendPolicy) { + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); + command.addByte(JDWP.EventKind.BREAKPOINT); + command.addByte(suspendPolicy); + command.addInt(1); + command.addByte(JDWP.EventModifierKind.LOCATION_ONLY); + command.addLocation(location); + return requestEvent(command, "BREAKPOINT"); + } + + /** + * Make request for BREAKPOINT event for the specified line of the given method. + */ + public int requestBreakpointEvent(byte typeTag, long classID, long methodID, + int lineNumber, byte suspendPolicy) { + long codeIndex = getCodeIndex(classID, methodID, lineNumber); + JDWP.Location location = new JDWP.Location(typeTag, classID, methodID, codeIndex); + return requestBreakpointEvent(location, suspendPolicy); + } + + /** + * Remove all existing BREAKPOINT event requests from debuggee. + */ + public void clearAllBreakpoints() { + String commandName = "EventRequest.ClearAllBreakpoints"; + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.ClearAllBreakpoints); + ReplyPacket reply = receiveReplyFor(command, commandName); + } + + // --------------------------------------------------- // + + /** + * Add IDs of supertypes (interfaces and classes) for given class to the lists. + */ + private void addSupertypes(long referenceTypeID, Vector supertypes, + Vector interfaces, Vector superclasses, + boolean interfaceOnly, boolean declared) { + + if (supertypes != null || interfaces != null) { + + // obtain list of direct implemented interfaces + String commandName = "ReferenceType.Interfaces"; + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Interfaces); + command.addReferenceTypeID(referenceTypeID); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + reply.resetPosition(); + + int count = reply.getInt(); + if (count < 0) { + throw new Failure("Negative number (" + count + + ") of declared interfaces received for referenceTypeID: " + + referenceTypeID); + } + + for (int i = 0; i < count; i++) { + long typeID = reply.getReferenceTypeID(); + if (!declared) { + addSupertypes(typeID, supertypes, interfaces, superclasses, + true, declared); + } + Long value = new Long(typeID); + if (supertypes != null) { + supertypes.add(value); + } + if (interfaces != null) { + interfaces.add(value); + } + } + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting interfeceIDs for referenceTypeID: " + + + referenceTypeID); + } + + } + + if (!interfaceOnly) { + + String commandName = "ClassType.Superclasses"; + CommandPacket command = new CommandPacket(JDWP.Command.ClassType.Superclass); + command.addReferenceTypeID(referenceTypeID); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + reply.resetPosition(); + + long typeID = reply.getReferenceTypeID(); + if (typeID != 0) { + if (!declared) { + addSupertypes(typeID, supertypes, interfaces, superclasses, + false, declared); + } + Long value = new Long(typeID); + if (supertypes != null) { + supertypes.add(value); + } + if (superclasses != null) { + superclasses.add(value); + } + } + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting superclass ID for classID: " + + + referenceTypeID); + } + + } + } + + /** + * Add attributes of fields of given class to the lists. + */ + private void addFields(long referenceTypeID, Vector IDs, Vector names, + Vector signatures, Vector modifiers, + boolean interfaceOnly, boolean declared) { + + if (!declared) { + Vector supertypes = new Vector(); + addSupertypes(referenceTypeID, supertypes, null, null, interfaceOnly, declared); + int count = supertypes.size(); + for (int i = 0; i < count; i++) { + long typeID = (supertypes.elementAt(i)).longValue(); + addFields(typeID, IDs, names, signatures, modifiers, + interfaceOnly, declared); + } + } + + String commandName = "ReferenceType.Fields"; + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); + command.addReferenceTypeID(referenceTypeID); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + reply.resetPosition(); + + int count = reply.getInt(); + if (count < 0) { + throw new Failure("Negative number (" + count + + ") of declared fields received for referenceTypeID: " + + referenceTypeID); + } + + for (int i = 0; i < count; i++) { + long id = reply.getFieldID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + if (IDs != null) + IDs.add(new Long(id)); + if (names != null) + names.add(name); + if (signatures != null) + signatures.add(signature); + if (modifiers != null) + modifiers.add(new Integer(modBits)); + } + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting fieldIDs for referenceTypeID: " + + + referenceTypeID); + } + } + + /** + * Add attributes of methods of given class to the lists. + */ + private void addMethods(long referenceTypeID, Vector IDs, Vector names, + Vector signatures, Vector modifiers, + boolean interfaceOnly, boolean declared) { + + if (!declared) { + Vector supertypes = new Vector(); + addSupertypes(referenceTypeID, supertypes, null, null, interfaceOnly, declared); + int count = supertypes.size(); + for (int i = 0; i < count; i++) { + long typeID = (supertypes.elementAt(i)).longValue(); + addMethods(typeID, IDs, names, signatures, modifiers, + interfaceOnly, declared); + } + } + + String commandName = "ReferenceType.Methods"; + CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Methods); + command.addReferenceTypeID(referenceTypeID); + ReplyPacket reply = receiveReplyFor(command, commandName); + + try { + reply.resetPosition(); + + int count = reply.getInt(); + if (count < 0) { + throw new Failure("Negative number (" + count + + ") of declared fields received for referenceTypeID: " + + referenceTypeID); + } + + for (int i = 0; i < count; i++) { + long id = reply.getMethodID(); + String name = reply.getString(); + String signature = reply.getString(); + int modBits = reply.getInt(); + + if (IDs != null) + IDs.add(new Long(id)); + if (names != null) + names.add(name); + if (signatures != null) + signatures.add(signature); + if (modifiers != null) + modifiers.add(new Integer(modBits)); + } + + } catch (BoundException e) { + complain("Unable to parse reply packet for " + commandName + " command:\n\t" + + e.getMessage()); + display("Reply packet:\n" + reply); + throw new Failure("Error occured while getting methodIDs for referenceTypeID: " + + + referenceTypeID); + } + } + + // --------------------------------------------------- // + + private static long[] makeListOfLongValues(Vector vector) { + int count = vector.size(); + long[] list = new long[count]; + for (int i = 0; i < count; i++) { + list[i] = (vector.elementAt(i)).longValue(); + } + return list; + } + + private static String[] makeListOfStringValues(Vector vector) { + int count = vector.size(); + String[] list = new String[count]; + for (int i = 0; i < count; i++) { + list[i] = vector.elementAt(i); + } + return list; + } + + // --------------------------------------------------- // + + /** + * Force debugge VM to exit using JDWP connection if possible. + */ + protected void killDebugee() { + // ignore + } + + /** + * Close transport channel and kill the debugee VM if it is not terminated yet. + */ + public void close() { + if (transport != null) { + try { + transport.close(); + } catch (IOException e) { + log.display("WARNING: Caught IOException while closing JDWP connection:\n\t" + + e); + } + } + super.close(); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/EventPacket.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/EventPacket.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; + +import java.util.Vector; + +/** + * This class represents a JDWP event packet. + */ +public class EventPacket extends CommandPacket { + + /** Offset of the "suspendPolicy" field in a JDWP event packet. */ + public final static int SuspendPolicyOffset = DataOffset; + + /** Offset of the "eventsCount" field in a JDWP event packet. */ + public final static int EventsCountOffset = SuspendPolicyOffset + JDWP.TypeSize.BYTE; + + /** Offset of the first "eventKind" field in a JDWP event packet. */ + public final static int FirstEventKindOffset = EventsCountOffset + JDWP.TypeSize.INT; + + /** + * Make an empty event packet. + */ + public EventPacket() { + super(JDWP.Command.Event.Composite, 0); + } + + /** + * Make event packet with data from the specified byte buffer. + */ +// public EventPacket(ByteBuffer packet) { + public EventPacket(Packet packet) { + super(packet); + } + + /** + * Return suspend policy of the events in the packet. + * + * throws BoundException if event packet structure is not valid + */ + public byte getSuspendPolicy() { + try { + return getByte(SuspendPolicyOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting event kind from header:\n\t" + + e); + } + } + + /** + * Return number of events in the packet. + * + * throws BoundException if event packet structure is not valid + */ + public int getEventsCount() { + try { + return getInt(EventsCountOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting event kind from header:\n\t" + + e); + } + } + + /** + * Return constant indicates kind of the first event in the packet. + * + * throws BoundException if event packet structure is not valid + */ + public int getEventKind() { + try { + return getByte(FirstEventKindOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting event kind from header:\n\t" + + e); + } + } + + /** + * Check event packet header. + * This method check if event packet has valid values in the header fields. + * + * @throws PacketFormatException if packet header fields have error or invalid values + */ + public void checkHeader() throws PacketFormatException { + super.checkHeader(); + if (getFullCommand() != JDWP.Command.Event.Composite) { + throw new PacketFormatException("Not Event.Composite command in the event packet header: " + + "0x" + toHexDecString(getFullCommand(), 4) ); + } + if (getFlags() != JDWP.Flag.EVENT_PACKET) { + throw new PacketFormatException("Unexpected flags in the event packet header: " + + "0x" + toHexDecString(getFlags(), 2)); + } +/* + if (getPacketID() != 0) { + throw new PacketFormatException("Non-zero packet ID in the event packet header: " + + getPacketID()); + } + */ + } + + /** + * Check event packet header for only one event of specified kind. + * This method check if event packet has valid values in the header fields. + * + * @throws PacketFormatException if packet header fields have error or invalid values + */ + public void checkHeader(int eventKind) throws PacketFormatException { + checkHeader(); + if (getEventsCount() != 1) { + throw new PacketFormatException("Not a single event in the event packet: " + + getEventsCount() + " events"); + } + if (getEventKind() != eventKind) { + throw new PacketFormatException("Unexpected event kind in the event packet: " + + "0x" + toHexDecString(getEventKind(), 2)); + } + } + + /** + * Return string representation of the event packet header. + */ + public String headerToString() { + return super.headerToString() + + " " + toHexString(SuspendPolicyOffset, 4) + " (policy): 0x" + toHexDecString(getSuspendPolicy(), 2) + "\n" + + " " + toHexString(EventsCountOffset, 4) + " (events): 0x" + toHexDecString(getEventsCount(), 8) + "\n" + + " " + toHexString(FirstEventKindOffset, 4) + " (kind): 0x" + toHexDecString(getEventKind(), 2) + "\n"; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/JDWP.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/JDWP.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,971 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; + +import nsk.share.Failure; + +/** + * This class contains JDWP constants, types and parameters. + */ +public class JDWP { + + public static class Error { + + public static final int NONE = 0; + public static final int INVALID_THREAD = 10; + public static final int INVALID_THREAD_GROUP = 11; + public static final int INVALID_PRIORITY = 12; + public static final int THREAD_NOT_SUSPENDED = 13; + public static final int THREAD_SUSPENDED = 14; + public static final int INVALID_OBJECT = 20; + public static final int INVALID_CLASS = 21; + public static final int CLASS_NOT_PREPARED = 22; + public static final int INVALID_METHODID = 23; + public static final int INVALID_LOCATION = 24; + public static final int INVALID_FIELDID = 25; + public static final int INVALID_FRAMEID = 30; + public static final int NO_MORE_FRAMES = 31; + public static final int OPAQUE_FRAME = 32; + public static final int NOT_CURRENT_FRAME = 33; + public static final int TYPE_MISMATCH = 34; + public static final int INVALID_SLOT = 35; + public static final int DUPLICATE = 40; + public static final int NOT_FOUND = 41; + public static final int INVALID_MONITOR = 50; + public static final int NOT_MONITOR_OWNER = 51; + public static final int INTERRUPT = 52; + public static final int INVALID_CLASS_FORMAT = 60; + public static final int CIRCULAR_CLASS_DEFINITION = 61; + public static final int FAILS_VERIFICATION = 62; + public static final int ADD_METHOD_NOT_IMPLEMENTED = 63; + public static final int SCHEMA_CHANGE_NOT_IMPLEMENTED = 64; + public static final int INVALID_TYPESTATE = 65; + public static final int HIERARCHY_CHANGE_NOT_IMPLEMENTED= 66; + public static final int DELETE_METHOD_NOT_IMPLEMENTED = 67; + public static final int UNSUPPORTED_VERSION = 68; + public static final int NAMES_DONT_MATCH = 69; + public static final int CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED = 70; + public static final int METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED = 71; + public static final int NOT_IMPLEMENTED = 99; + public static final int NULL_POINTER = 100; + public static final int ABSENT_INFORMATION = 101; + public static final int INVALID_EVENT_TYPE = 102; + public static final int ILLEGAL_ARGUMENT = 103; + public static final int OUT_OF_MEMORY = 110; + public static final int ACCESS_DENIED = 111; + public static final int VM_DEATH = 112; + public static final int INTERNAL = 113; + public static final int UNATTACHED_THREAD = 115; + public static final int INVALID_TAG = 500; + public static final int ALREADY_INVOKING = 502; + public static final int INVALID_INDEX = 503; + public static final int INVALID_LENGTH = 504; + public static final int INVALID_STRING = 506; + public static final int INVALID_CLASS_LOADER = 507; + public static final int INVALID_ARRAY = 508; + public static final int TRANSPORT_LOAD = 509; + public static final int TRANSPORT_INIT = 510; + public static final int NATIVE_METHOD = 511; + public static final int INVALID_COUNT = 512; + + } + + public static class Flag { + + public static final byte NONE = (byte)0; + public static final byte REPLY_PACKET = (byte)0x80; + public static final byte EVENT_PACKET = NONE; + + } + + public static class EventKind { + + public static final byte VM_INIT = (byte)90; + public static final byte VM_START = VM_INIT; + public static final byte VM_DISCONNECTED = (byte)100; + public static final byte VM_DEATH = (byte)99; + + public static final byte THREAD_START = (byte)6; + public static final byte THREAD_END = (byte)7; + public static final byte THREAD_DEATH = THREAD_END; + + public static final byte CLASS_PREPARE = (byte)8; + public static final byte CLASS_LOAD = (byte)10; + public static final byte CLASS_UNLOAD = (byte)9; + + public static final byte METHOD_ENTRY = (byte)40; + public static final byte METHOD_EXIT = (byte)41; + + public static final byte FIELD_ACCESS = (byte)20; + public static final byte FIELD_MODIFICATION = (byte)21; + + public static final byte EXCEPTION = (byte)4; + public static final byte EXCEPTION_CATCH = (byte)30; + + public static final byte FRAME_POP = (byte)3; + + public static final byte BREAKPOINT = (byte)2; + + public static final byte SINGLE_STEP = (byte)1; + + public static final byte USER_DEFINED = (byte)5; + + } + + public static class EventModifierKind { + + public static final byte COUNT = (byte)1; + public static final byte CONDITIONAL = (byte)2; + public static final byte THREAD_ONLY = (byte)3; + public static final byte CLASS_ONLY = (byte)4; + public static final byte CLASS_MATCH = (byte)5; + public static final byte CLASS_EXCLUDE = (byte)6; + public static final byte LOCATION_ONLY = (byte)7; + public static final byte EXCEPTION_ONLY = (byte)8; + public static final byte FIELD_ONLY = (byte)9; + public static final byte STEP = (byte)10; + public static final byte INSTANCE_ONLY = (byte)11; + }; + + public static class ThreadStatus { + + public static final int ZOMBIE = 0; + public static final int RUNNING = 1; + public static final int SLEEPING = 2; + public static final int MONITOR = 3; + public static final int WAIT = 4; + + } + + public static class SuspendStatus { + + public static final int SUSPEND_STATUS_SUSPENDED = 0x1; + + } + + public static class ClassStatus { + + public static final int PREPARED = 2; + public static final int VERIFIED = 1; + public static final int INITIALIZED = 4; + public static final int ERROR = 8; + + } + + public static class TypeTag { + + public static final byte CLASS = (byte)1; + public static final byte INTERFACE = (byte)2; + public static final byte ARRAY = (byte)3; + + } + + public static class Tag { + + public static final byte ARRAY = (byte)91; + public static final byte BYTE = (byte)66; + public static final byte CHAR = (byte)67; + public static final byte OBJECT = (byte)76; + public static final byte FLOAT = (byte)70; + public static final byte DOUBLE = (byte)68; + public static final byte INT = (byte)73; + public static final byte LONG = (byte)74; + public static final byte SHORT = (byte)83; + public static final byte VOID = (byte)86; + public static final byte BOOLEAN = (byte)90; + public static final byte STRING = (byte)115; + public static final byte THREAD = (byte)116; + public static final byte THREAD_GROUP = (byte)103; + public static final byte CLASS_LOADER = (byte)108; + public static final byte CLASS_OBJECT = (byte)99; + + } + + public static class StepDepth { + + public static final int INTO = 0; + public static final int OVER = 1; + public static final int OUT = 2; + + } + + public static class StepSize { + + public static final int MIN = 0; + public static final int LINE = 1; + + } + + public static class SuspendPolicy { + + public static final byte NONE = (byte)0; + public static final byte EVENT_THREAD = (byte)1; + public static final byte ALL = (byte)2; + + } + + public static class InvokeOptions { + + public static final int INVOKE_SINGLE_THREADED = 0x01; + public static final int INVOKE_NONVIRTUAL = 0x02; + + } + + public static class TypeSize { + + // VM independent type sizes + + public static final int BYTE = 1; + public static final int BOOLEAN = 1; + public static final int CHAR = 2; + public static final int SHORT = 2; + public static final int FLOAT = 4; + public static final int INT = 4; + public static final int LONG = 8; + public static final int DOUBLE = 8; + + public static final int TAG = 1; + public static final int LOCATION_INDEX = 8; + + // basic VM specific type sizes + + public static int OBJECT_ID = 8; + public static int METHOD_ID = 4; + public static int FIELD_ID = 4; + public static int FRAME_ID = 4; + + // derivative VM specific type sizes + + public static int TAGGED_OBJECT_ID = TAG + OBJECT_ID; + + public static int THREAD_ID = OBJECT_ID; + public static int THREAD_GROUP_ID = OBJECT_ID; + public static int STRING_ID = OBJECT_ID; + public static int CLASS_LOADER_ID = OBJECT_ID; + public static int CLASS_OBJECT_ID = OBJECT_ID; + public static int REFERENCE_TYPE_ID = OBJECT_ID; + + public static int CLASS_ID = REFERENCE_TYPE_ID; + public static int INTERFACE_ID = REFERENCE_TYPE_ID; + public static int ARRAY_ID = REFERENCE_TYPE_ID; + + public static int LOCATION = TAG + CLASS_ID + METHOD_ID + LOCATION_INDEX; + + /** + * Calculate type sizes based on VM dependent basic type sizes. + */ + public static void CalculateSizes() { + + TAGGED_OBJECT_ID = TAG + OBJECT_ID; + + THREAD_ID = OBJECT_ID; + THREAD_GROUP_ID = OBJECT_ID; + STRING_ID = OBJECT_ID; + CLASS_LOADER_ID = OBJECT_ID; + CLASS_OBJECT_ID = OBJECT_ID; + REFERENCE_TYPE_ID = OBJECT_ID; + + CLASS_ID = REFERENCE_TYPE_ID; + INTERFACE_ID = REFERENCE_TYPE_ID; + ARRAY_ID = REFERENCE_TYPE_ID; + + LOCATION = TAG + CLASS_ID + METHOD_ID + LOCATION_INDEX; + } + + } + + public static class ModifierFlag { + + public static final int PUBLIC = 0x0001; + public static final int PRIVATE = 0x0002; + public static final int PROTECTED = 0x0004; + public static final int STATIC = 0x0008; + public static final int FINAL = 0x0010; + public static final int SUPER = 0x0020; + public static final int VOLATILE = 0x0040; + public static final int TRANSIENT = 0x0080; + public static final int SYNCHRONIZED = 0x0020; + public static final int NATIVE = 0x0100; + public static final int INTERFACE = 0x0200; + public static final int ABSTRACT = 0x0400; + public static final int SYNTHETIC = 0xF0000000; + + public static final int CLASS_MASK = PUBLIC | FINAL | SUPER | INTERFACE | ABSTRACT; + public static final int FIELD_MASK = PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT; + public static final int METHOD_MASK = PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | NATIVE | ABSTRACT; + + } + + public static class CommandSet { + + public static final byte VirtualMachine = (byte)0x01; + public static final byte ReferenceType = (byte)0x02; + public static final byte ClassType = (byte)0x03; + public static final byte ArrayType = (byte)0x04; + public static final byte InterfaceType = (byte)0x05; + public static final byte Method = (byte)0x06; + public static final byte Field = (byte)0x08; + public static final byte ObjectReference = (byte)0x09; + public static final byte StringReference = (byte)0x0A; + public static final byte ThreadReference = (byte)0x0B; + public static final byte ThreadGroupReference = (byte)0x0C; + public static final byte ArrayReferemce = (byte)0x0D; + public static final byte ClassLoaderReference = (byte)0x0E; + public static final byte EventRequest = (byte)0x0F; + public static final byte StackFrame = (byte)0x10; + public static final byte ClassObjectReference = (byte)0x11; + public static final byte Event = (byte)0x40; + + } + + // command names, used only for debug output + public static HashMap commandNames = new HashMap(); + + static + { + commandNames.put(Command.ObjectReference.ReferringObjects, "ObjectReference.ReferringObjects"); + commandNames.put(Command.ReferenceType.Instances, "ReferenceType.Instances"); + commandNames.put(Command.ReferenceType.ClassFileVersion, "ReferenceType.ClassFileVersion"); + commandNames.put(Command.ReferenceType.ConstantPool, "ReferenceType.ConstantPool"); + commandNames.put(Command.ThreadReference.OwnedMonitorsStackDepthInfo, "ThreadReference.OwnedMonitorsStackDepthInfo"); + commandNames.put(Command.ThreadReference.ForceEarlyReturn, "ThreadReference.ForceEarlyReturn"); + commandNames.put(Command.VirtualMachine.InstanceCounts, "VirtualMachine.InstanceCounts"); + } + + public static class Command { + + public static class VirtualMachine { + + public static final int Version = 0x0101; + public static final int ClassesBySignature = 0x0102; + public static final int AllClasses = 0x0103; + public static final int AllThreads = 0x0104; + public static final int TopLevelThreadGroups = 0x0105; + public static final int Dispose = 0x0106; + public static final int IDSizes = 0x0107; + public static final int Suspend = 0x0108; + public static final int Resume = 0x0109; + public static final int Exit = 0x010A; + public static final int CreateString = 0x010B; + public static final int Capabilities = 0x010C; + public static final int ClassPaths = 0x010D; + public static final int DisposeObjects = 0x010E; + public static final int HoldEvents = 0x010F; + public static final int ReleaseEvents = 0x0110; + + // since JDK-1.4 + public static final int CapabilitiesNew = 0x0111; + public static final int RedefineClasses = 0x0112; + public static final int SetDefaultStratum = 0x0113; + + // since JDK-1.5 + public static final int AllClassesWithGeneric = 0x0114; + + // since JDK-1.6 + public static final int InstanceCounts = 0x0115; + } + + public static class ReferenceType { + + public static final int Signature = 0x0201; + public static final int ClassLoader = 0x0202; + public static final int Modifiers = 0x0203; + public static final int Fields = 0x0204; + public static final int Methods = 0x0205; + public static final int GetValues = 0x0206; + public static final int SourceFile = 0x0207; + public static final int NestedTypes = 0x0208; + public static final int Status = 0x0209; + public static final int Interfaces = 0x020A; + public static final int ClassObject = 0x020B; + + // since JDK-1.4 + public static final int SourceDebugExtension = 0x020C; + + // since JDK-1.5 + public static final int SignatureWithGeneric = 0x020D; + public static final int FieldsWithGeneric = 0x020E; + public static final int MethodsWithGeneric = 0x020F; + + // since JDK-1.6 + public static final int Instances = 0x0210; + public static final int ClassFileVersion = 0x0211; + public static final int ConstantPool = 0x0212; + } + + public static class ClassType { + + public static final int Superclass = 0x0301; + public static final int SetValues = 0x0302; + public static final int InvokeMethod = 0x0303; + public static final int NewInstance = 0x0304; + + } + + public static class ArrayType { + + public static final int NewInstance = 0x0401; + + } + + public static class InterfaceType { + + } + + public static class Method { + + public static final int LineTable = 0x0601; + public static final int VariableTable = 0x0602; + public static final int Bytecodes = 0x0603; + + // since JDK-1.4 + public static final int IsObsolete = 0x0604; + + // since JDK-1.5 + public static final int VariableTableWithGeneric = 0x0605; + + } + + public static class Field { + + } + + public static class ObjectReference { + + public static final int ReferenceType = 0x0901; + public static final int GetValues = 0x0902; + public static final int SetValues = 0x0903; + public static final int MonitorInfo = 0x0905; + public static final int InvokeMethod = 0x0906; + public static final int DisableCollection = 0x0907; + public static final int EnableCollection = 0x0908; + public static final int IsCollected = 0x0909; + + // since JDK-1.6 + public static final int ReferringObjects = 0x090A; + } + + public static class StringReference { + + public static final int Value = 0x0A01; + + } + + public static class ThreadReference { + + public static final int Name = 0x0B01; + public static final int Suspend = 0x0B02; + public static final int Resume = 0x0B03; + public static final int Status = 0x0B04; + public static final int ThreadGroup = 0x0B05; + public static final int Frames = 0x0B06; + public static final int FrameCount = 0x0B07; + public static final int OwnedMonitors = 0x0B08; + public static final int CurrentContendedMonitor = 0x0B09; + public static final int Stop = 0x0B0A; + public static final int Interrupt = 0x0B0B; + public static final int SuspendCount = 0x0B0C; + public static final int PopTopFrame = 0x0B0D; + + // since JDK-1.6 + public static final int OwnedMonitorsStackDepthInfo = 0x0B0D; + public static final int ForceEarlyReturn = 0x0B0E; + } + + public static class ThreadGroupReference { + + public static final int Name = 0x0C01; + public static final int Parent = 0x0C02; + public static final int Children = 0x0C03; + + } + + public static class ArrayReference { + + public static final int Length = 0x0D01; + public static final int GetValues = 0x0D02; + public static final int SetValues = 0x0D03; + + } + + public static class ClassLoaderReference { + + public static final int VisibleClasses = 0x0E01; + + } + + public static class EventRequest { + + public static final int Set = 0x0F01; + public static final int Clear = 0x0F02; + public static final int ClearAllBreakpoints = 0x0F03; + + } + + public static class StackFrame { + + public static final int GetValues = 0x1001; + public static final int SetValues = 0x1002; + public static final int ThisObject = 0x1003; + + // since JDK-1.4 + public static final int PopFrames = 0x1004; + + } + + public static class ClassObjectReference { + + public static final int ReflectedType = 0x1101; + + } + + public static class Event { + + public static final int Composite = 0x4064; + + } + + } // end of class Command + + public static class Capability { + + // common capabilities + public static final int CAN_WATCH_FIELD_MODIFICATION = 0; + public static final int CAN_WATCH_FIELD_ACCESS = 1; + public static final int CAN_GET_BYTECODES = 2; + public static final int CAN_GET_SYNTHETIC_ATTRIBUTE = 3; + public static final int CAN_GET_OWNED_MONITOR_INFO = 4; + public static final int CAN_GET_CURRENT_CONTENDED_MONITOR = 5; + public static final int CAN_GET_MONITOR_INFO = 6; + + // new capabilities (since JDWP version 1.4) + public static final int CAN_REDEFINE_CLASSES = 7; + public static final int CAN_ADD_METHODR_INFO = 8; + public static final int CAN_UNRESTRICTEDLY_REDEFINE_CLASSES = 9; + public static final int CAN_POP_FRAMES = 10; + public static final int CAN_USE_INSTANCE_FILTER = 11; + public static final int CAN_GET_SOURCE_DEBUG_EXTENSION = 12; + public static final int CAN_REQUEST_VMDEATH_EVENT = 13; + public static final int CAN_SET_DEFAULT_STRATUM = 14; + } + + public static class Location extends ByteBuffer { + + public static int TAG_OFFSET = 0; + public static int CLASS_ID_OFFSET = TAG_OFFSET + JDWP.TypeSize.TAG; + public static int METHOD_ID_OFFSET = CLASS_ID_OFFSET + JDWP.TypeSize.CLASS_ID; + public static int INDEX_OFFSET = METHOD_ID_OFFSET + JDWP.TypeSize.METHOD_ID; + + private static void calculateOffsets() { + CLASS_ID_OFFSET = TAG_OFFSET + JDWP.TypeSize.TAG; + METHOD_ID_OFFSET = CLASS_ID_OFFSET + JDWP.TypeSize.CLASS_ID; + INDEX_OFFSET = METHOD_ID_OFFSET + JDWP.TypeSize.METHOD_ID; + } + + public Location(byte typeTag, long classID, long methodID, long index) { + this(); + // 1 byte type tag + putTag(typeTag); + // classID + putClassID(classID); + // methodID + putMethodID(methodID); + // 8 bytes index + putIndex(index); + } + + public Location() { + super(JDWP.TypeSize.LOCATION, 0); + addBytes((byte)0, TypeSize.LOCATION); + + // calculate offsets for VM-dependent type sizes + calculateOffsets(); + } + + public final byte getTag() { + try { + return getByte(TAG_OFFSET); + } catch (BoundException e) { + throw new Failure("Unable to get tag from location:\n\t" + e); + } + } + + public final long getClassID() { + try { + return getID(CLASS_ID_OFFSET, JDWP.TypeSize.CLASS_ID); + } catch (BoundException e) { + throw new Failure("Unable to get classID from location:\n\t" + e); + } + } + + public final long getMethodID() { + try { + return getID(METHOD_ID_OFFSET, JDWP.TypeSize.METHOD_ID); + } catch (BoundException e) { + throw new Failure("Unable to get methodID from location:\n\t" + e); + } + } + + public final long getIndex() { + try { + return getID(INDEX_OFFSET, JDWP.TypeSize.LOCATION_INDEX); + } catch (BoundException e) { + throw new Failure("Unable to get code index from location:\n\t" + e); + } + } + + public final void putTag(byte tag) { + try { + putByte(TAG_OFFSET, tag); + } catch (BoundException e) { + throw new Failure("Unable to put tag into location:\n\t" + e); + } + } + + public final void putClassID(long classID) { + try { + putID(CLASS_ID_OFFSET, classID, JDWP.TypeSize.CLASS_ID); + } catch (BoundException e) { + throw new Failure("Unable to put classID into location:\n\t" + e); + } + } + + public final void putMethodID(long methodID) { + try { + putID(METHOD_ID_OFFSET, methodID, JDWP.TypeSize.METHOD_ID); + } catch (BoundException e) { + throw new Failure("Unable to put methodID into location:\n\t" + e); + } + } + + public final void putIndex(long index) { + try { + putID(INDEX_OFFSET, index, JDWP.TypeSize.LOCATION_INDEX); + } catch (BoundException e) { + throw new Failure("Unable to put code index into location:\n\t" + e); + } + } + + public String toString() { + return "Location(" + + "tag=" + getTag() + ", " + + "classID=" + getClassID() + ", " + + "methodID=" + getMethodID() + ", " + + "index=" + getIndex() + + ")"; + } + + } // end of class Location + + public static class UntaggedValue { + + public Object value = null; + + public UntaggedValue() { + } + + public UntaggedValue(Object value) { + this.value = value; + } + + public Object getValue() { + return value; + } + + public int length(byte tag) { + int valueSize = 0; + try { + switch (tag) { + case JDWP.Tag.BYTE: { + valueSize = JDWP.TypeSize.BYTE; + } break; + case JDWP.Tag.CHAR: { + valueSize = JDWP.TypeSize.CHAR; + } break; + case JDWP.Tag.FLOAT: { + valueSize = JDWP.TypeSize.FLOAT; + } break; + case JDWP.Tag.DOUBLE: { + valueSize = JDWP.TypeSize.DOUBLE; + } break; + case JDWP.Tag.INT: { + valueSize = JDWP.TypeSize.INT; + } break; + case JDWP.Tag.SHORT: { + valueSize = JDWP.TypeSize.SHORT; + } break; + case JDWP.Tag.BOOLEAN: { + valueSize = JDWP.TypeSize.BYTE; + } break; + case JDWP.Tag.LONG: { + valueSize = JDWP.TypeSize.LONG; + } break; + case JDWP.Tag.VOID: { + valueSize = 0; + } break; + case JDWP.Tag.ARRAY: + case JDWP.Tag.OBJECT: + case JDWP.Tag.STRING: + case JDWP.Tag.THREAD: + case JDWP.Tag.THREAD_GROUP: + case JDWP.Tag.CLASS_LOADER: + case JDWP.Tag.CLASS_OBJECT: { + valueSize = JDWP.TypeSize.OBJECT_ID; + } break; + default: { + throw new Failure("Unknown tag found while putting value into packet: " + tag); + } + } + } catch (ClassCastException e) { + throw new Failure("Wrong tag " + tag + " found while putting value to packet: " + value); + } + return JDWP.TypeSize.TAG + valueSize; + } + + public void addValueTo(Packet packet, byte tag) { + if (value == null) { + throw new Failure("Unable to put null value into packet: " + this); + } + try { + switch (tag) { + case JDWP.Tag.BYTE: { + byte castedValue = ((Byte)value).byteValue(); + packet.addByte(castedValue); + } break; + case JDWP.Tag.CHAR: { + char castedValue = ((Character)value).charValue(); + packet.addChar(castedValue); + } break; + case JDWP.Tag.FLOAT: { + float castedValue = ((Float)value).floatValue(); + packet.addFloat(castedValue); + } break; + case JDWP.Tag.DOUBLE: { + double castedValue = ((Double)value).doubleValue(); + packet.addDouble(castedValue); + } break; + case JDWP.Tag.INT: { + int castedValue = ((Integer)value).intValue(); + packet.addInt(castedValue); + } break; + case JDWP.Tag.SHORT: { + short castedValue = ((Short)value).shortValue(); + packet.addShort(castedValue); + } break; + case JDWP.Tag.BOOLEAN: { + boolean castedValue = ((Boolean)value).booleanValue(); + packet.addByte((byte)(castedValue? 1 : 0)); + } break; + case JDWP.Tag.LONG: { + long castedValue = ((Long)value).longValue(); + packet.addLong(castedValue); + } break; + case JDWP.Tag.VOID: { + } break; + case JDWP.Tag.ARRAY: + case JDWP.Tag.OBJECT: + case JDWP.Tag.STRING: + case JDWP.Tag.THREAD: + case JDWP.Tag.THREAD_GROUP: + case JDWP.Tag.CLASS_LOADER: + case JDWP.Tag.CLASS_OBJECT: { + long castedValue = ((Long)value).longValue(); + packet.addObjectID(castedValue); + } break; + default: { + throw new Failure("Unknown tag found while putting value into packet: " + tag); + } + } + } catch (ClassCastException e) { + throw new Failure("Wrong tag " + tag + " found while putting value to packet: " + value); + } + } + + public void getValueFrom(Packet packet, byte tag) throws BoundException { + switch (tag) { + case JDWP.Tag.BYTE: { + byte castedValue = packet.getByte(); + value = new Byte(castedValue); + } break; + case JDWP.Tag.CHAR: { + char castedValue = packet.getChar(); + value = new Character(castedValue); + } break; + case JDWP.Tag.FLOAT: { + float castedValue = packet.getFloat(); + value = new Float(castedValue); + } break; + case JDWP.Tag.DOUBLE: { + double castedValue = packet.getDouble(); + value = new Double(castedValue); + } break; + case JDWP.Tag.INT: { + int castedValue = packet.getInt(); + value = new Integer(castedValue); + } break; + case JDWP.Tag.SHORT: { + short castedValue = packet.getShort(); + value = new Short(castedValue); + } break; + case JDWP.Tag.BOOLEAN: { + byte castedValue = packet.getByte(); + value = new Boolean(castedValue != 0); + } break; + case JDWP.Tag.LONG: { + long castedValue = packet.getLong(); + value = new Long(castedValue); + } break; + case JDWP.Tag.VOID: { + value = new Long(0); + } break; + case JDWP.Tag.ARRAY: + case JDWP.Tag.OBJECT: + case JDWP.Tag.STRING: + case JDWP.Tag.THREAD: + case JDWP.Tag.THREAD_GROUP: + case JDWP.Tag.CLASS_LOADER: + case JDWP.Tag.CLASS_OBJECT: { + long castedValue = packet.getObjectID(); + value = new Long(castedValue); + } break; + default: { + throw new Failure("Unknown tag found while reading value from packet: " + tag); + } + } + } + + public String toString(byte tag) { + if (value == null) { + return "null"; + } + String type = null; + try { + switch (tag) { + case JDWP.Tag.BYTE: { + type = "BYTE"; + } break; + case JDWP.Tag.CHAR: { + type = "CHAR"; + } break; + case JDWP.Tag.FLOAT: { + type = "FLOAT"; + } break; + case JDWP.Tag.DOUBLE: { + type = "DOUBLE"; + } break; + case JDWP.Tag.INT: { + type = "INT"; + } break; + case JDWP.Tag.SHORT: { + type = "SHORT"; + } break; + case JDWP.Tag.BOOLEAN: { + type = "BOOLEAN"; + } break; + case JDWP.Tag.LONG: { + type = "LONG"; + } break; + case JDWP.Tag.VOID: { + type = "VOID"; + } break; + case JDWP.Tag.ARRAY: { + type = "ARRAY_ID"; + } break; + case JDWP.Tag.OBJECT: { + type = "OBJECT_ID"; + } break; + case JDWP.Tag.STRING: { + type = "STRING_ID"; + } break; + case JDWP.Tag.THREAD: { + type = "THREAD_ID"; + } break; + case JDWP.Tag.THREAD_GROUP: { + type = "THREAD_GROUP_ID"; + } break; + case JDWP.Tag.CLASS_LOADER: { + type = "CLASS_LOADER_ID"; + } break; + case JDWP.Tag.CLASS_OBJECT: { + type = "CLASS_OBJECT_ID"; + } break; + default: { + throw new Failure("Unknown tag found while converting value into string: " + tag); + } + } + return "(" + type + ")" + value; + } catch (ClassCastException e) { + throw new Failure("Wrong tag " + tag + " found while putting value to packet: " + value); + } + } + + } // end of class Value + + public static class Value extends UntaggedValue { + + public static final int TAG_OFFSET = 0; + public static final int VALUE_OFFSET = TAG_OFFSET + TypeSize.TAG; + + public byte tag = 0; + + public Value() { + } + + public Value(byte tag, Object value) { + super(value); + this.tag = tag; + } + + public byte getTag() { + return tag; + } + + public int length() { + return super.length(tag); + } + + public void addValueTo(Packet packet) { + if (value == null) { + throw new Failure("Unable to put null value into packet: " + this); + } + packet.addByte(tag); + super.addValueTo(packet, tag); + } + + public void getValueFrom(Packet packet) throws BoundException { + tag = packet.getByte(); + super.getValueFrom(packet, tag); + } + + public String toString() { + return super.toString(tag); + } + + } // end of class Value + +} // end of class JDWP diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Packet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Packet.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; + +import java.util.Vector; +import java.io.*; + +/** + * This class represents a JDWP packet. + */ +public class Packet extends ByteBuffer { + + /** JDWP packet flags constant. */ +// public final static byte flNoFlags = (byte)0x0; + /** JDWP packet flags constant. */ +// public final static byte flReply = (byte)0x80; + + /** Offset of "length" field of JDWP packet. */ + public final static int LengthOffset = 0; + /** Offset of "id" field of JDWP packet. */ + public final static int IdOffset = LengthOffset + 4; + /** Offset of "flags" field of JDWP packet. */ + public final static int FlagsOffset = IdOffset + 4; + /** Offset of full "command" field of JDWP packet. */ + public final static int FullCommandOffset = FlagsOffset + 1; + /** Offset of "command" field of JDWP command packet. */ + public final static int CommandSetOffset = FullCommandOffset; + /** Offset of "command" field of JDWP command packet. */ + public final static int CommandOffset = CommandSetOffset + 1; + /** Offset of "error" field of JDWP reply packet. */ + public final static int ErrorCodeOffset = FlagsOffset + 1; + /** Offset of "data" section of JDWP packet. */ + public final static int DataOffset = FullCommandOffset + 2; + + /** Size of JDWP packet header. */ + public final static int PacketHeaderSize = DataOffset; + + /** + * Makes empty JDWP packet. + */ + public Packet() { + super(); + resetBuffer(); + } + + /** + * Makes JDWP packet with data from the specified byte buffer. + */ +// public Packet(ByteBuffer packet) { + public Packet(Packet packet) { + super(packet); + resetPosition(); + } + + /** + * Clear buffer of the packet. + */ + public void resetBuffer() { + super.resetBuffer(); + while (length() < PacketHeaderSize) + addByte((byte) 0); + setLength(); + resetPosition(); + } + + /** + * Return current position from begin of packet data area. + */ + public int currentDataPosition() { + return currentPosition() - PacketHeaderSize; + } + + /** + * Return value to the "length" field of JDWP packet. + */ + public int getLength() { + try { + return getInt(LengthOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting packet length value from header:\n\t" + + e); + } + } + + /** + * Assign specified value to the "length" field of JDWP packet. + */ + public void setLength(int length) { + try { + putInt(LengthOffset, length); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while setting packet length value into header:\n\t" + + e); + } + } + + /** + * Assign packet length value to the "length" field of JDWP packet. + */ + public void setLength() { + setLength(length()); + } + + /** + * Return value of the "id" field of JDWP packet. + */ + public int getPacketID() { + try { + return getInt(IdOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting packet ID value from header:\n\t" + + e); + } + } + + /** + * Assign value to the "id" field of JDWP packet. + */ + public void setPacketID(int Id) { + try { + putInt(IdOffset, Id); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while setting packet ID value into header:\n\t" + + e); + } + } + + /** + * Return value of the "flags" field of JDWP packet. + */ + public byte getFlags() { + try { + return getByte(FlagsOffset); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting packet flags value from header:\n\t" + + e); + } + } + + /** + * Assign value to the "flags" field of JDWP packet. + */ + public void setFlags(byte flags) { + try { + putByte(FlagsOffset, flags); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while setting packet flags value into header:\n\t" + + e); + } + } + + /** + * Sets the current parser position to "data" field of JDWP packet. + */ + public void resetPosition() { + resetPosition(PacketHeaderSize); + } + + /** + * Return size of the "data" part of JDWP packet. + */ + public int getDataSize() { + return length() - PacketHeaderSize; + } + + ////////////////////////////////////////////////////////////////////////// + + /** + * Append fieldID to the end of this buffer. + */ + public void addFieldID(long b) { + addID(b, JDWP.TypeSize.FIELD_ID); + } + + /** + * Append methodID to the end of this buffer. + */ + public void addMethodID(long b) { + addID(b, JDWP.TypeSize.METHOD_ID); + } + + /** + * Append objectID to the end of this buffer. + */ + public void addObjectID(long b) { + addID(b, JDWP.TypeSize.OBJECT_ID); + } + + /** + * Append referenceID to the end of this buffer. + */ + public void addReferenceTypeID(long b) { + addID(b, JDWP.TypeSize.REFERENCE_TYPE_ID); + } + + /** + * Append frameID to the end of this buffer. + */ + public void addFrameID(long b) { + addID(b, JDWP.TypeSize.FRAME_ID); + } + + /** + * Append string value (an UTF-8 encoded string, not zero terminated, + * preceded by a four-byte integer length) to the end of this buffer. + */ + public void addString(String value) { + final int count = JDWP.TypeSize.INT + value.length(); + addInt(value.length()); + try { + addBytes(value.getBytes("UTF-8"), 0, value.length()); + } catch (UnsupportedEncodingException e) { + throw new Failure("Unsupported UTF-8 ecnoding while adding string value to JDWP packet:\n\t" + + e); + } + } + + /** + * Append location value to the end of this buffer. + */ + public void addLocation(JDWP.Location location) { + addBytes(location.getBytes(), 0, location.length()); + } + + /** + * Append untagged value to the end of this buffer. + */ + public void addUntaggedValue(JDWP.UntaggedValue value, byte tag) { + value.addValueTo(this, tag); + } + + /** + * Append tagged value to the end of this buffer. + */ + public void addValue(JDWP.Value value) { + value.addValueTo(this); + } + + ////////////////////////////////////////////////////////////////////////// + // get packet data + ////////////////////////////////////////////////////////////////////////// + + /** + * Read a fieldID value from byte buffer at the current parser position. + * + * @throws BoundException if there is no valid value bytes at the given position + */ + public long getFieldID() throws BoundException { + return getID(JDWP.TypeSize.FIELD_ID); + } + + /** + * Read a methodID value from byte buffer at the current parser position. + * + * @throws BoundException if there is no valid value bytes at the given position + */ + public long getMethodID() throws BoundException { + return getID(JDWP.TypeSize.METHOD_ID); + } + + /** + * Read an objectID value from byte buffer at the current parser position. + * + * @throws BoundException if there is no valid value bytes at the given position + */ + public long getObjectID() throws BoundException { + return getID(JDWP.TypeSize.OBJECT_ID); + } + + /** + * Read a referenceTypeID value from byte buffer at the current parser position. + * + * @throws BoundException if there is no valid value bytes at the given position + */ + public long getReferenceTypeID() throws BoundException { + return getID(JDWP.TypeSize.REFERENCE_TYPE_ID); + } + + /** + * Read a frameID value from byte buffer at the current parser position. + * + * @throws BoundException if there is no valid value bytes at the given position + */ + public long getFrameID() throws BoundException { + return getID(JDWP.TypeSize.FRAME_ID); + } + + /** + * Read from this buffer a string value at the current parser + * position and returns this value. + * + * @throws BoundException if there are no valid string bytes in the buffer + */ + public String getString() throws BoundException { + final int count = JDWP.TypeSize.INT; + int available = length() - currentPosition(); + if (count > available) { + throw new BoundException("Unable to get " + count + " bytes of string length value at " + + offsetString() + " (available bytes: " + available + ")" ); + } + + int len = getInt(); + + if (len < 0) + throw new BoundException("Negative length of string to get: " + len); + + if (len == 0) + return ""; + + available = length() - currentPosition(); + if (len > available) { + throw new BoundException("Unable to get " + len + " bytes of string value at " + + offsetString() + " (available bytes: " + available + ")" ); + } + + byte[] s = new byte[len]; + for (int i = 0; i < len; i++) + s[i] = getByte(); + + try { + return new String(s, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new Failure("Unsupported UTF-8 ecnoding while extracting string value from JDWP packet:\n\t" + + e); + } + } + + /** + * Reads from this buffer an location value at the current parser + * position and returns this value. + * + * @throws BoundException if there are no enough bytes in the buffer + */ + public JDWP.Location getLocation() throws BoundException { + final int count = JDWP.TypeSize.LOCATION; + final int available = length() - currentPosition(); + if (count > available) { + throw new BoundException("Unable to get " + count + " bytes of location value at " + + offsetString() + " (available bytes: " + available + ")" ); + } + + JDWP.Location location = new JDWP.Location(); + try { + for (int i = 0; i < JDWP.TypeSize.LOCATION; i++) { + location.putByte(i, getByte()); + } + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + count + " bytes of location value:\n\t" + e); + }; + + return location; + } + + /** + * Reads from this buffer an untagged value at the current parser + * position and returns this value. + * + * @throws BoundException if there are no enough bytes in the buffer + */ + public JDWP.UntaggedValue getUntaggedValue(byte tag) throws BoundException { + JDWP.UntaggedValue value = new JDWP.UntaggedValue(); + try { + value.getValueFrom(this, tag); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + " bytes of a value:\n\t" + e); + }; + + return value; + } + + /** + * Reads from this buffer a tagged value at the current parser + * position and returns this value. + * + * @throws BoundException if there are no enough bytes in the buffer + */ + public JDWP.Value getValue() throws BoundException { + JDWP.Value value = new JDWP.Value(); + try { + value.getValueFrom(this); + } + catch (BoundException e) { + throw new TestBug("Caught unexpected bound exception while getting " + + " bytes of a value:\n\t" + e); + }; + + return value; + } + + + //////////////////////////////////////////////////////////////// + + /** + * Read packet bytes from the stream. + * + * @throws IOException if error occured when reading bytes + */ + public void readFrom(Transport transport) throws IOException { + resetBuffer(); + +// System.err.println("Reading packet header"); + try { + for (int i = 0; i < PacketHeaderSize; i++) { + byte b = transport.read(); + putByte(i, b); + } + } + catch (BoundException e) { + throw new TestBug(e); + } + + int length = getLength(); + + checkSpace(length - PacketHeaderSize); + +// System.err.println("Packet size: " + length); + for (int i = PacketHeaderSize; i < length; i++) { + byte b = transport.read(); + addByte(b); + } +// System.err.println("Packet read successfully"); + } + + /** + * Write packet bytes to the stream. + * + * @throws IOException if error occured when reading bytes + */ + public void writeTo(Transport transport) throws IOException { + setLength(); +// System.err.println("Writing packet bytes: " + length()); + transport.write(bytes, 0, length()); + } + + /** + * Check packet header. + * This method check if packet has valid values in header fields. + * + * @throws PacketFormatException if packet header fields has error or invalid values + */ + public void checkHeader() throws PacketFormatException { + if (getLength() != length()) { + throw new PacketFormatException("Unexpected packet length value in the header:" + + getLength()); + } + } + + /** + * Check if packet is parsed totally and no trailing bytes left unparsed. + * This method check if packet has valid values in header fields. + * + * @throws PacketFormatException if there are trailing bytes left unparsed + */ + public void checkParsed() throws PacketFormatException { + if (! isParsed()) { + throw new PacketFormatException("Extra trailing bytes found in the packet at: " + + offsetString()); + } + } + + /** + * Return string representation of the packet header. + */ + public String headerToString() { + return "Packet header (" + PacketHeaderSize + " bytes):" + "\n" + + " " + toHexString(LengthOffset, 4) + " (length) : 0x" + toHexDecString(getLength(), 8) + "\n" + + " " + toHexString(IdOffset, 4) + " (id) : 0x" + toHexDecString(getPacketID(), 8) + "\n" + + " " + toHexString(FlagsOffset, 4) + " (flags) : 0x" + toHexDecString(getFlags(), 2) + "\n"; + } + + /** + * Return string representation of the packet. + */ + public String toString() { + return headerToString() + + "Entire packet (" + length() + " bytes): " + "\n" + + super.toString(0) + + "Packet end"; + } + + /** + * Exception indicated that packet has an ivnalid structure. + */ + class PacketFormatException extends BoundException { + PacketFormatException(String message) { + super(message); + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/ReplyPacket.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/ReplyPacket.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; +import java.util.Vector; + +/** + * This class represents a JDWP reply packet. + */ +public class ReplyPacket extends Packet { + + /** Error code constant. */ +// public final static int errOk = JDWP.Error.NONE; + /** Error code constant. */ +// public final static int errWrongPacketSize = 0x400; + /** Error code constant. */ +// public final static int errNotAvailable = 0x401; + /** Error code constant. */ +// public final static int errEvent = 0x4064; + + /** + * Make empty reply packet. + */ + public ReplyPacket() { + super(); + } + + /** + * Make reply packet with data from the specified byte buffer. + */ +// public ReplyPacket(ByteBuffer packet) { + public ReplyPacket(Packet packet) { + super(packet); + } + + /** + * Return value of the "error code" field of JDWP reply packet. + */ + public int getErrorCode() { + + int err = 0; + try { + err = (int) getID(ErrorCodeOffset, 2); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while getting error code from header:\n\t" + + e); + } + + return err; + } + + /** + * Set value of the "error code" field of JDWP reply packet. + */ + public void setErrorCode(long err) { + try { + putID(ErrorCodeOffset, err, 2); + } + catch (BoundException e) { + throw new Failure("Caught unexpected exception while setting error code into header:\n\t" + + e); + } + } + + /** + * Check reply packet header. + * This method check if reply packet has valid values in the header fields. + * + * @throws PacketFormatException if packet header fields have error or invalid values + */ +/* + protected void checkHeaderForReplyOrEvent() throws PacketFormatException { + super.checkHeader(); + } + */ + + /** + * Check reply packet header. + * This method check if reply packet has valid values in the header fields. + * + * @throws PacketFormatException if packet header fields have error or invalid values + */ + public void checkHeader() throws PacketFormatException { +// checkHeaderForReplyOrEvent(); + super.checkHeader(); + if (getFlags() != JDWP.Flag.REPLY_PACKET) { + throw new PacketFormatException("Unexpected flags in reply packet header: " + + "0x" + toHexDecString(getFlags(), 2)); + } + if (getErrorCode() != JDWP.Error.NONE) { + throw new PacketFormatException("Unexpected error code in reply packet header: " + + "0x" + toHexDecString(getErrorCode(), 4)); + } + } + + /** + * Check reply packet header for specified reply ID. + * This method check if reply packet has valid values in the header fields. + * + * @throws PacketFormatException if packet header fields have error or invalid values + */ + public void checkHeader(int id) throws PacketFormatException { + checkHeader(); + if (getPacketID() != id) { + throw new PacketFormatException("Unexpected ID in reply packet header: " + + getPacketID()); + } + } + + /** + * Return string representation of the reply packet header. + */ + public String headerToString() { + String s; + + if (getFlags() == 0) + s = " (command)"; + else + s = " (error) "; + + return super.headerToString() + + " " + toHexString(CommandOffset, 4) + s + ": 0x" + toHexDecString(getErrorCode(), 4) + "\n"; + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/SocketTransport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/SocketTransport.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; + +import java.io.*; +import java.net.*; + +/** + * This class represents a socket transport for JDWP. + */ +public class SocketTransport extends Transport { + + /** + * Socket for established JDWP connection. + */ + private Socket socket = null; + + /** + * ServerSocket for listening JDWP connection. + */ + private ServerSocket serverSocket = null; + + /** + * Input stream of socket. + */ + private InputStream in = null; + + /** + * Output stream of socket. + */ + private OutputStream out = null; + + /** + * Port to listen to. + */ + int listenPort = 0; + + /** + * Make SocketTransport object with providing specified Log. + */ + public SocketTransport(Log log) { + super(log); + } + + /** + * Bind for connection from target VM to specified port number. + * If given port number is 0 then bind to any free port number. + * + * @return port number which this transport is listening for + */ + public int bind(int port) + throws IOException { + serverSocket = new ServerSocket(); + if (port == 0) { + // Only need SO_REUSEADDR if we're using a fixed port. If we + // start seeing EADDRINUSE due to collisions in free ports + // then we should retry the bind() a few times. + display("port == 0, disabling SO_REUSEADDR"); + serverSocket.setReuseAddress(false); + } + serverSocket.bind(new InetSocketAddress(port)); + listenPort = serverSocket.getLocalPort(); + return listenPort; + } + + /** + * Attach to the target VM for specified host name and port number. + */ + public void attach(String ServerName, int PortNumber) + throws UnknownHostException, IOException { + for (int i = 0; i < Binder.CONNECT_TRIES; i++ ) { + try { + socket = new Socket(ServerName, PortNumber); + display("JDWP socket connection established"); +// socket.setTcpNoDelay(true); + in = socket.getInputStream(); + out = socket.getOutputStream(); + return; + } catch (IOException e) { + display("Attempt #" + i + " to establish JDWP socket connection failed:\n\t" + e); + try { + Thread.currentThread().sleep(Binder.CONNECT_TRY_DELAY); + } catch (InterruptedException ie) { + ie.printStackTrace(log.getOutStream()); + throw new Failure("Thread interrupted while establishing JDWP connection: \n\t" + + ie); + } + } + } + throw new IOException("Timeout exceeded while establishing JDWP socket connection to " + + ServerName + ":" + PortNumber); + } + + /** + * Accept connection from target VM for already boud port. + */ + public void accept() + throws IOException { + + if (serverSocket == null) + throw new Failure("Attempt to accept JDWP socket connection from unbound port"); + + socket = serverSocket.accept(); + serverSocket.close(); + serverSocket = null; + + in = socket.getInputStream(); + out = socket.getOutputStream(); + } + + /** + * Close socket and streams. + */ + public void close() throws IOException { + + if (socket == null) + return; + + if (out != null) { + flush(); + out.close(); + } + + if (in != null) { + in.close(); + } + + if (socket != null) { + socket.close(); + socket = null; + } + + if (serverSocket != null) { + serverSocket.close(); + serverSocket = null; + } + } + + /** + * Return number of bytes that can be read. + */ + public int available() throws IOException { + return in.available(); + }; + + /** + * Flush bytes being buffered for writing if any. + */ + public void flush() throws IOException { + out.flush(); + } + + /** + * Set timeout for reading data in milliseconds. + */ + public void setReadTimeout(long millisecs) throws IOException { + socket.setSoTimeout((int)millisecs); + } + + /** + * Read the next byte of data from the socket. + * The value byte is returned as an int in the range 0 to 255. + * If no byte is available, the value -1 is returned. + */ + public byte read() throws IOException { + int b = in.read(); + if (b < 0) { + throw new IOException("JDWP socket connection closed by remote host"); + } + return (byte) b; + }; + + /** + * Write the specified byte to the socket. + */ + public void write(int b) throws IOException { + out.write(b); + }; +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/TestDebuggerType1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/TestDebuggerType1.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 nsk.share.jdwp; + +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; + +/* + * This class can be used as base for debugger. + * Class initialize log, pipe, debuggee, transport. + * + * Subclasses should implement method doTest() and provide debugee class name via method getDebugeeClassName() + */ +abstract public class TestDebuggerType1 { + protected ArgumentHandler argumentHandler; + + protected Log log; + + protected IOPipe pipe; + + protected Debugee debuggee; + + protected Transport transport; + + private boolean success = true; + + public static String createTypeSignature(String name) { + return "L" + name.replace('.', '/') + ";"; + } + + protected void setSuccess(boolean value) { + success = value; + } + + protected boolean getSuccess() { + return success; + } + + protected String getDebugeeClassName() { + return AbstractJDWPDebuggee.class.getName(); + } + + abstract protected void doTest(); + + // receive reply for given command + protected ReplyPacket getReply(CommandPacket command, boolean expectError, int errorCode) throws IOException, + BoundException { + log.display("Waiting for reply packet"); + ReplyPacket reply = new ReplyPacket(); + transport.read(reply); + log.display("Reply packet received:\n" + reply); + + if (expectError) { + if (reply.getErrorCode() != errorCode) { + setSuccess(false); + log.complain("Reply doesn't contain expected error " + errorCode + ", error code = " + + reply.getErrorCode()); + } else { + log.display("Expected error: " + errorCode); + } + } else { + log.display("Checking reply packet header"); + reply.checkHeader(command.getPacketID()); + log.display("Parsing reply packet:"); + reply.resetPosition(); + } + + return reply; + } + + // receive reply for given command + protected ReplyPacket getReply(CommandPacket command) throws IOException, BoundException { + return getReply(command, false, 0); + } + + // initialize test and remove unsupported by nsk.share.jdwp.ArgumentHandler + // arguments + // (ArgumentHandler constructor throws BadOption exception if command line + // contains unrecognized by ArgumentHandler options) + protected String[] doInit(String args[]) { + return args; + } + + public int runIt(String args[], PrintStream out) { + argumentHandler = new ArgumentHandler(doInit(args)); + // make log for debugger messages + log = new Log(out, argumentHandler); + + // execute test and display results + try { + log.display("\n>>> Preparing debugee for testing \n"); + + // launch debugee + Binder binder = new Binder(argumentHandler, log); + log.display("Launching debugee"); + debuggee = binder.bindToDebugee(getDebugeeClassName()); + transport = debuggee.getTransport(); + pipe = debuggee.createIOPipe(); + + // make debuggee ready for testing + prepareDebugee(); + + doTest(); + } catch (Throwable t) { + setSuccess(false); + log.complain("Caught unexpected exception:\n" + t); + t.printStackTrace(log.getOutStream()); + } finally { + if (pipe != null) + quitDebugee(); + } + + if (getSuccess()) { + log.display("TEST PASSED"); + return Consts.TEST_PASSED; + } else { + log.display("TEST FAILED"); + return Consts.TEST_FAILED; + } + } + + protected void prepareDebugee() { + // wait for VM_INIT event from debugee + log.display("Waiting for VM_INIT event"); + debuggee.waitForVMInit(); + + // query debugee for VM-dependent ID sizes + log.display("Querying for IDSizes"); + debuggee.queryForIDSizes(); + + // resume initially suspended debugee + log.display("Resuming debugee VM"); + debuggee.resume(); + + // wait for READY signal from debugee + log.display("Waiting for signal from debugee: " + AbstractDebuggeeTest.COMMAND_READY); + + if (!isDebuggeeReady()) + return; + } + + protected boolean isDebuggeeReady() { + String signal = pipe.readln(); + log.display("Received signal from debugee: " + signal); + + if (!signal.equals(AbstractDebuggeeTest.COMMAND_READY)) { + setSuccess(false); + log.complain("Unexpected signal received form debugee: " + signal + " (expected: " + + AbstractDebuggeeTest.COMMAND_READY + ")"); + return false; + } + + return true; + } + + protected void quitDebugee() { + // send debugee signal to quit + log.display("Sending signal to debugee: " + AbstractDebuggeeTest.COMMAND_QUIT); + pipe.println(AbstractDebuggeeTest.COMMAND_QUIT); + + // wait for debugee exits + log.display("Waiting for debugee exits"); + int code = debuggee.waitFor(); + + // analize debugee exit status code + if (code == (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.display("Debugee PASSED with exit code: " + code); + } else { + setSuccess(false); + log.complain("Debugee FAILED with exit code: " + code); + } + } + + protected int defaultBreakpointRequestID; + + // query debuggee for objectID value of static class field + protected long queryObjectID(long classID, String fieldName, byte tag) { + // get fieledID for static field (declared in the class) + long fieldID = debuggee.getClassFieldID(classID, fieldName, true); + + // get value of the field + JDWP.Value value = debuggee.getStaticFieldValue(classID, fieldID); + + // check that value has correct tag + if (value.getTag() != tag) { + throw new Failure("Wrong objectID tag received from field \"" + fieldName + "\": " + value.getTag() + + " (expected: " + tag + ")"); + } + + // extract objectID from the value + long objectID = ((Long) value.getValue()).longValue(); + + return objectID; + } + + // query debuggee for objectID value of static class field + protected long queryObjectID(long classID, String fieldName) { + + // get fieledID for static field (declared in the class) + long fieldID = debuggee.getClassFieldID(classID, fieldName, true); + + // get value of the field + JDWP.Value value = debuggee.getStaticFieldValue(classID, fieldID); + + // extract objectID from the value + long objectID = ((Long) value.getValue()).longValue(); + + return objectID; + } + + protected void clearRequest(byte eventKind, int requestID) { + try { + CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); + command.addByte(eventKind); + command.addInt(requestID); + command.setLength(); + transport.write(command); + ReplyPacket reply; + + reply = getReply(command); + + if (!reply.isParsed()) { + log.complain("Extra trailing bytes found in request reply packet at: " + reply.offsetString()); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + // receives JDWP event, checks that only one event was received and checks + // event kind and event's request id + protected EventPacket receiveSingleEvent(byte expectedEventKind, int expectedRequestID) { + try { + EventPacket eventPacket = debuggee.getEventPacket(); + + eventPacket.checkHeader(); + eventPacket.resetPosition(); + + eventPacket.getByte(); + + int eventCount = eventPacket.getInt(); + + if (eventCount != 1) { + setSuccess(false); + log.complain("Unexpected event count: " + eventCount + ", expected is " + 1); + } + + byte eventKind = eventPacket.getByte(); + + if (eventKind != expectedEventKind) { + setSuccess(false); + log.complain("Unexpected event kind: " + eventKind + ", expected is " + expectedEventKind); + } + + int requestID = eventPacket.getInt(); + + if (requestID != expectedRequestID) { + setSuccess(false); + log.complain("Unexpected request id: " + requestID + ", expected is " + expectedRequestID); + } + + return eventPacket; + } catch (Exception e) { + setSuccess(false); + log.complain("Caught exception while testing JDWP command: " + e); + e.printStackTrace(log.getOutStream()); + + return null; + } + } + + + private boolean currentSuccess = false; + protected void forceGC() { + pipe.println(AbstractDebuggeeTest.COMMAND_FORCE_GC); + if (!isDebuggeeReady()) + return; + currentSuccess = getSuccess(); + } + + // Get GC statistics + protected void resetStatusIfGC() { + pipe.println(AbstractDebuggeeTest.COMMAND_GC_COUNT); + String command = pipe.readln(); + if (command.startsWith(AbstractDebuggeeTest.COMMAND_GC_COUNT)) { + if (!isDebuggeeReady()) { + return; + } + if (Integer.valueOf(command.substring(AbstractDebuggeeTest.COMMAND_GC_COUNT.length() + 1)) > 0) { + log.display("WARNING: The GC worked during tests. Results are skipped."); + setSuccess(currentSuccess); + } + return; + } + setSuccess(false); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Transport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Transport.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package nsk.share.jdwp; + +import nsk.share.*; + +import java.io.IOException; +//import java.util.Vector; + +/** + * This class represents an abstract transport for JDWP. + */ +public abstract class Transport extends Log.Logger { + + public static final String LOG_PREFIX = "transport> "; + + /** + * Make base Transport object providing with specified Log. + */ + public Transport(Log log) { + super(log, LOG_PREFIX); + } + + /** + * Return number of bytes that can be received. + */ + public abstract int available() throws IOException; + + /** + * Flushe bytes being buffered for writing if any. + */ + public abstract void flush() throws IOException; + + /** + * Receive the next byte of data. + * + * The value byte is returned as an int in the range 0 to 255. + * If no byte is available, the value -1 is returned. + */ + public abstract byte read() throws IOException; + + /** + * Send the specified byte. + */ + public abstract void write(int b) throws IOException; + + /** + * Send the specified bytes. + */ + public void write(byte[] b, int off, int len) throws IOException { + for (int i = 0; i < len; i++) + write(b[off + i]); + } + + /** + * Receive bytes of JDWP packet for default timeout. + */ + public void read(Packet packet) throws IOException { + packet.readFrom(this); + } + + /** + * Send and flushe bytes of JDWP packet. + */ + public void write(Packet packet) throws IOException { + packet.writeTo(this); + flush(); + } + + /** + * Perform JDWP "handshake" procedure. + */ + public void handshake() throws IOException { + + String hs = "JDWP-Handshake"; + byte[] hsb = hs.getBytes(); + + write(hsb, 0, hsb.length); + flush(); + + try { + Thread.currentThread().sleep(500); + } catch (InterruptedException e) { + throw new Failure(e); + } + + int received = 0; + for (int i = 0; i < Binder.CONNECT_TRIES; i++) { + received = available(); + if (received < hsb.length) { +// System.err.println("Failed to hadshake try #" + i + ", bytes: " + received); + try { + Thread.currentThread().sleep(Binder.CONNECT_TRY_DELAY); + } catch (InterruptedException e) { + throw new Failure("Thread interrupted while sleeping between connection attempts:\n\t" + + e); + } + } else { +// System.err.println("Successed to hadshake try #" + i + ", bytes: " + received); + for (int j = 0; j < hsb.length; j++) { + byte b = (byte) (read() & 0xFF); + if (b != hsb[j]) + throw new IOException("Target VM failed to handshake: unexpected byte #" + j + + ": " + b + " (expected:" + hsb[j] + ")"); + } + return; + } + } + + throw new IOException("Target VM failed to handshake: too few bytes in reply: " + + received + "(expected: " + hsb.length + ")"); + } + + /** + * Set timeout for reading data in milliseconds. + * Timeout of 0 means wait infinitly. + */ + public abstract void setReadTimeout(long millisecs) throws IOException; + + /** + * Close JDWP connection. + */ + public abstract void close() throws IOException; + + /** + * Perform finalization of object by closing JDWP connection. + */ + protected void finalize() throws Throwable { + close(); + } + +} diff -r d66751750b72 -r c10dbcaed048 test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.h --- a/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.h Wed May 30 11:36:46 2018 -0700 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.h Thu May 31 13:39:26 2018 -0700 @@ -27,9 +27,17 @@ /*************************************************************/ #include +#include /*************************************************************/ +#if defined(_LP64) && defined(__APPLE__) +#define JLONG_FORMAT "%ld" +#else // _LP64 && __APPLE__ +#define JLONG_FORMAT "%" PRId64 +#endif // _LP64 && __APPLE__ + + /** * Use examples: * diff -r d66751750b72 -r c10dbcaed048 test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/ChaCha20KAT.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/ChaCha20KAT.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8153029 + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main ChaCha20KAT + * @summary ChaCha20 Cipher Implementation (KAT) + */ + +import java.util.*; +import java.security.GeneralSecurityException; +import javax.crypto.Cipher; +import javax.crypto.spec.ChaCha20ParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.AEADBadTagException; +import java.nio.ByteBuffer; +import jdk.test.lib.Convert; + +public class ChaCha20KAT { + public static class TestData { + public TestData(String name, String keyStr, String nonceStr, int ctr, + int dir, String inputStr, String aadStr, String outStr) { + testName = Objects.requireNonNull(name); + key = Convert.hexStringToByteArray(Objects.requireNonNull(keyStr)); + nonce = Convert.hexStringToByteArray( + Objects.requireNonNull(nonceStr)); + if ((counter = ctr) < 0) { + throw new IllegalArgumentException( + "counter must be 0 or greater"); + } + direction = dir; + if ((direction != Cipher.ENCRYPT_MODE) && + (direction != Cipher.DECRYPT_MODE)) { + throw new IllegalArgumentException( + "Direction must be ENCRYPT_MODE or DECRYPT_MODE"); + } + input = Convert.hexStringToByteArray( + Objects.requireNonNull(inputStr)); + aad = (aadStr != null) ? + Convert.hexStringToByteArray(aadStr) : null; + expOutput = Convert.hexStringToByteArray( + Objects.requireNonNull(outStr)); + } + + public final String testName; + public final byte[] key; + public final byte[] nonce; + public final int counter; + public final int direction; + public final byte[] input; + public final byte[] aad; + public final byte[] expOutput; + } + + public static final List testList = new LinkedList() {{ + add(new TestData("RFC 7539 Sample Test Vector", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "000000000000004a00000000", + 1, Cipher.ENCRYPT_MODE, + "4c616469657320616e642047656e746c656d656e206f662074686520636c6173" + + "73206f66202739393a204966204920636f756c64206f6666657220796f75206f" + + "6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" + + "637265656e20776f756c642062652069742e", + null, + "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b" + + "f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8" + + "07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736" + + "5af90bbf74a35be6b40b8eedf2785e42874d")); + add(new TestData("RFC 7539 Test Vector 1 (all zeroes)", + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + 0, Cipher.ENCRYPT_MODE, + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000", + null, + "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7" + + "da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586")); + add(new TestData("RFC 7539 Test Vector 2", + "0000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000002", + 1, Cipher.ENCRYPT_MODE, + "416e79207375626d697373696f6e20746f20746865204945544620696e74656e" + + "6465642062792074686520436f6e7472696275746f7220666f72207075626c69" + + "636174696f6e20617320616c6c206f722070617274206f6620616e2049455446" + + "20496e7465726e65742d4472616674206f722052464320616e6420616e792073" + + "746174656d656e74206d6164652077697468696e2074686520636f6e74657874" + + "206f6620616e204945544620616374697669747920697320636f6e7369646572" + + "656420616e20224945544620436f6e747269627574696f6e222e205375636820" + + "73746174656d656e747320696e636c756465206f72616c2073746174656d656e" + + "747320696e20494554462073657373696f6e732c2061732077656c6c20617320" + + "7772697474656e20616e6420656c656374726f6e696320636f6d6d756e696361" + + "74696f6e73206d61646520617420616e792074696d65206f7220706c6163652c" + + "207768696368206172652061646472657373656420746f", + null, + "a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec" + + "2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d" + + "4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e527950" + + "42bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85a" + + "d00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259d" + + "c4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b" + + "0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6c" + + "cc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0b" + + "c39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f" + + "5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e6" + + "98ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab" + + "7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221")); + add(new TestData("RFC 7539 Test Vector 3", + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "000000000000000000000002", + 42, Cipher.ENCRYPT_MODE, + "2754776173206272696c6c69672c20616e642074686520736c6974687920746f" + + "7665730a446964206779726520616e642067696d626c6520696e207468652077" + + "6162653a0a416c6c206d696d737920776572652074686520626f726f676f7665" + + "732c0a416e6420746865206d6f6d65207261746873206f757467726162652e", + null, + "62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf" + + "166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553eb" + + "f39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f77" + + "04c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1")); + }}; + + public static final List aeadTestList = + new LinkedList() {{ + add(new TestData("RFC 7539 Sample AEAD Test Vector", + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "070000004041424344454647", + 1, Cipher.ENCRYPT_MODE, + "4c616469657320616e642047656e746c656d656e206f662074686520636c6173" + + "73206f66202739393a204966204920636f756c64206f6666657220796f75206f" + + "6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" + + "637265656e20776f756c642062652069742e", + "50515253c0c1c2c3c4c5c6c7", + "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" + + "3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" + + "92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" + + "3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd060" + + "0691")); + add(new TestData("RFC 7539 A.5 Sample Decryption", + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "000000000102030405060708", + 1, Cipher.DECRYPT_MODE, + "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb2" + + "4c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf" + + "332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c855" + + "9797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4" + + "b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523e" + + "af4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a" + + "0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a10" + + "49e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29" + + "a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38", + "f33388860000000000004e91", + "496e7465726e65742d4472616674732061726520647261667420646f63756d65" + + "6e74732076616c696420666f722061206d6178696d756d206f6620736978206d" + + "6f6e74687320616e64206d617920626520757064617465642c207265706c6163" + + "65642c206f72206f62736f6c65746564206279206f7468657220646f63756d65" + + "6e747320617420616e792074696d652e20497420697320696e617070726f7072" + + "6961746520746f2075736520496e7465726e65742d4472616674732061732072" + + "65666572656e6365206d6174657269616c206f7220746f206369746520746865" + + "6d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67" + + "726573732e2fe2809d")); + }}; + + + public static void main(String args[]) throws Exception { + int testsPassed = 0; + int testNumber = 0; + + System.out.println("----- Single-part (byte[]) Tests -----"); + for (TestData test : testList) { + System.out.println("*** Test " + ++testNumber + ": " + + test.testName); + if (runSinglePartTest(test)) { + testsPassed++; + } + } + System.out.println(); + + System.out.println("----- Single-part (ByteBuffer) Tests -----"); + for (TestData test : testList) { + System.out.println("*** Test " + ++testNumber + ": " + + test.testName); + if (runByteBuffer(test)) { + testsPassed++; + } + } + System.out.println(); + + System.out.println("----- Multi-part Tests -----"); + for (TestData test : testList) { + System.out.println("*** Test " + ++testNumber + ": " + + test.testName); + if (runMultiPartTest(test)) { + testsPassed++; + } + } + System.out.println(); + + System.out.println("----- AEAD Tests -----"); + for (TestData test : aeadTestList) { + System.out.println("*** Test " + ++testNumber + ": " + + test.testName); + if (runAEADTest(test)) { + testsPassed++; + } + } + System.out.println(); + + System.out.println("Total tests: " + testNumber + + ", Passed: " + testsPassed + ", Failed: " + + (testNumber - testsPassed)); + if (testsPassed != testNumber) { + throw new RuntimeException("One or more tests failed. " + + "Check output for details"); + } + } + + private static boolean runSinglePartTest(TestData testData) + throws GeneralSecurityException { + boolean encRes = false; + boolean decRes = false; + byte[] encryptedResult; + byte[] decryptedResult; + + // Get a Cipher instance and set up the parameters + Cipher mambo = Cipher.getInstance("ChaCha20"); + SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20"); + ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec( + testData.nonce, testData.counter); + + // Encrypt our input + mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec); + encryptedResult = mambo.doFinal(testData.input); + + if (!Arrays.equals(encryptedResult, testData.expOutput)) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(testData.expOutput, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(encryptedResult, 16, "\n", " ")); + System.out.println(); + } else { + encRes = true; + } + + // Decrypt the result of the encryption operation + mambo = Cipher.getInstance("ChaCha20"); + mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec); + decryptedResult = mambo.doFinal(encryptedResult); + + if (!Arrays.equals(decryptedResult, testData.input)) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(testData.input, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(decryptedResult, 16, "\n", " ")); + System.out.println(); + } else { + decRes = true; + } + + return (encRes && decRes); + } + + private static boolean runMultiPartTest(TestData testData) + throws GeneralSecurityException { + boolean encRes = false; + boolean decRes = false; + + // Get a cipher instance and initialize it + Cipher mambo = Cipher.getInstance("ChaCha20"); + SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20"); + ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec( + testData.nonce, testData.counter); + + byte[] encryptedResult = new byte[testData.input.length]; + mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec); + System.out.print("Encrypt - "); + doMulti(mambo, testData.input, encryptedResult); + + if (!Arrays.equals(encryptedResult, testData.expOutput)) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(testData.expOutput, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(encryptedResult, 16, "\n", " ")); + System.out.println(); + } else { + encRes = true; + } + + // Decrypt the result of the encryption operation + mambo = Cipher.getInstance("ChaCha20"); + byte[] decryptedResult = new byte[encryptedResult.length]; + mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec); + System.out.print("Decrypt - "); + doMulti(mambo, encryptedResult, decryptedResult); + + if (!Arrays.equals(decryptedResult, testData.input)) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(testData.input, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(decryptedResult, 16, "\n", " ")); + System.out.println(); + } else { + decRes = true; + } + + return (encRes && decRes); + } + + private static void doMulti(Cipher c, byte[] input, byte[] output) + throws GeneralSecurityException { + int offset = 0; + boolean done = false; + Random randIn = new Random(System.currentTimeMillis()); + + // Send small updates between 1 - 8 bytes in length until we get + // 8 or less bytes from the end of the input, then finalize. + System.out.println("Input length: " + input.length); + System.out.print("Multipart (bytes in/out): "); + while (!done) { + int mPartLen = randIn.nextInt(8) + 1; + int bytesLeft = input.length - offset; + int processed; + if (mPartLen < bytesLeft) { + System.out.print(mPartLen + "/"); + processed = c.update(input, offset, mPartLen, + output, offset); + offset += processed; + System.out.print(processed + " "); + } else { + processed = c.doFinal(input, offset, bytesLeft, + output, offset); + System.out.print(bytesLeft + "/" + processed + " "); + done = true; + } + } + System.out.println(); + } + + private static boolean runByteBuffer(TestData testData) + throws GeneralSecurityException { + boolean encRes = false; + boolean decRes = false; + + // Get a cipher instance and initialize it + Cipher mambo = Cipher.getInstance("ChaCha20"); + SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20"); + ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec( + testData.nonce, testData.counter); + mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec); + + ByteBuffer bbIn = ByteBuffer.wrap(testData.input); + ByteBuffer bbEncOut = ByteBuffer.allocate( + mambo.getOutputSize(testData.input.length)); + ByteBuffer bbExpOut = ByteBuffer.wrap(testData.expOutput); + + mambo.doFinal(bbIn, bbEncOut); + bbIn.rewind(); + bbEncOut.rewind(); + + if (bbEncOut.compareTo(bbExpOut) != 0) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(bbExpOut, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(bbEncOut, 16, "\n", " ")); + System.out.println(); + } else { + encRes = true; + } + + // Decrypt the result of the encryption operation + mambo = Cipher.getInstance("ChaCha20"); + mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec); + System.out.print("Decrypt - "); + ByteBuffer bbDecOut = ByteBuffer.allocate( + mambo.getOutputSize(bbEncOut.remaining())); + + mambo.doFinal(bbEncOut, bbDecOut); + bbEncOut.rewind(); + bbDecOut.rewind(); + + if (bbDecOut.compareTo(bbIn) != 0) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(bbIn, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(bbDecOut, 16, "\n", " ")); + System.out.println(); + } else { + decRes = true; + } + + return (encRes && decRes); + } + + private static boolean runAEADTest(TestData testData) + throws GeneralSecurityException { + boolean result = false; + + Cipher mambo = Cipher.getInstance("ChaCha20-Poly1305"); + SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20"); + IvParameterSpec mamboSpec = new IvParameterSpec(testData.nonce); + + mambo.init(testData.direction, mamboKey, mamboSpec); + + byte[] out = new byte[mambo.getOutputSize(testData.input.length)]; + int outOff = 0; + try { + mambo.updateAAD(testData.aad); + outOff += mambo.update(testData.input, 0, testData.input.length, + out, outOff); + outOff += mambo.doFinal(out, outOff); + } catch (AEADBadTagException abte) { + // If we get a bad tag or derive a tag mismatch, log it + // and register it as a failure + System.out.println("FAIL: " + abte); + return false; + } + + if (!Arrays.equals(out, testData.expOutput)) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(testData.expOutput, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(out, 16, "\n", " ")); + System.out.println(); + } else { + result = true; + } + + return result; + } + + /** + * Dump the hex bytes of a buffer into string form. + * + * @param data The array of bytes to dump to stdout. + * @param itemsPerLine The number of bytes to display per line + * if the {@code lineDelim} character is blank then all bytes + * will be printed on a single line. + * @param lineDelim The delimiter between lines + * @param itemDelim The delimiter between bytes + * + * @return The hexdump of the byte array + */ + private static String dumpHexBytes(byte[] data, int itemsPerLine, + String lineDelim, String itemDelim) { + return dumpHexBytes(ByteBuffer.wrap(data), itemsPerLine, lineDelim, + itemDelim); + } + + private static String dumpHexBytes(ByteBuffer data, int itemsPerLine, + String lineDelim, String itemDelim) { + StringBuilder sb = new StringBuilder(); + if (data != null) { + data.mark(); + int i = 0; + while (data.remaining() > 0) { + if (i % itemsPerLine == 0 && i != 0) { + sb.append(lineDelim); + } + sb.append(String.format("%02X", data.get())).append(itemDelim); + i++; + } + data.reset(); + } + + return sb.toString(); + } +} + diff -r d66751750b72 -r c10dbcaed048 test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/ChaCha20NoReuse.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/ChaCha20NoReuse.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8153029 + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main ChaCha20NoReuse + * @summary ChaCha20 Cipher Implementation (key/nonce reuse protection) + */ + +import java.util.*; +import javax.crypto.Cipher; +import java.security.spec.AlgorithmParameterSpec; +import javax.crypto.spec.ChaCha20ParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.AEADBadTagException; +import javax.crypto.SecretKey; +import java.security.InvalidKeyException; +import jdk.test.lib.Convert; + +public class ChaCha20NoReuse { + + private static final String ALG_CC20 = "ChaCha20"; + private static final String ALG_CC20_P1305 = "ChaCha20-Poly1305"; + + /** + * Basic TestMethod interface definition. + */ + public interface TestMethod { + /** + * Runs the actual test case + * + * @param algorithm the algorithm to use (e.g. ChaCha20, etc.) + * + * @return true if the test passes, false otherwise. + */ + boolean run(String algorithm); + + /** + * Check if this TestMethod can be run for this algorithm. Some tests + * are specific to ChaCha20 or ChaCha20-Poly1305, so this method + * can be used to determine if a given Cipher type is appropriate. + * + * @param algorithm the algorithm to use. + * + * @return true if this test can be run on this algorithm, + * false otherwise. + */ + boolean isValid(String algorithm); + } + + public static class TestData { + public TestData(String name, String keyStr, String nonceStr, int ctr, + int dir, String inputStr, String aadStr, String outStr) { + testName = Objects.requireNonNull(name); + key = Convert.hexStringToByteArray(Objects.requireNonNull(keyStr)); + nonce = Convert.hexStringToByteArray( + Objects.requireNonNull(nonceStr)); + if ((counter = ctr) < 0) { + throw new IllegalArgumentException( + "counter must be 0 or greater"); + } + direction = dir; + if ((direction != Cipher.ENCRYPT_MODE) && + (direction != Cipher.DECRYPT_MODE)) { + throw new IllegalArgumentException( + "Direction must be ENCRYPT_MODE or DECRYPT_MODE"); + } + input = Convert.hexStringToByteArray( + Objects.requireNonNull(inputStr)); + aad = (aadStr != null) ? + Convert.hexStringToByteArray(aadStr) : null; + expOutput = Convert.hexStringToByteArray( + Objects.requireNonNull(outStr)); + } + + public final String testName; + public final byte[] key; + public final byte[] nonce; + public final int counter; + public final int direction; + public final byte[] input; + public final byte[] aad; + public final byte[] expOutput; + } + + public static final List testList = new LinkedList() {{ + add(new TestData("RFC 7539 Sample Test Vector [ENCRYPT]", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "000000000000004a00000000", + 1, Cipher.ENCRYPT_MODE, + "4c616469657320616e642047656e746c656d656e206f662074686520636c6173" + + "73206f66202739393a204966204920636f756c64206f6666657220796f75206f" + + "6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" + + "637265656e20776f756c642062652069742e", + null, + "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b" + + "f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8" + + "07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736" + + "5af90bbf74a35be6b40b8eedf2785e42874d")); + add(new TestData("RFC 7539 Sample Test Vector [DECRYPT]", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "000000000000004a00000000", + 1, Cipher.DECRYPT_MODE, + "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b" + + "f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8" + + "07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736" + + "5af90bbf74a35be6b40b8eedf2785e42874d", + null, + "4c616469657320616e642047656e746c656d656e206f662074686520636c6173" + + "73206f66202739393a204966204920636f756c64206f6666657220796f75206f" + + "6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" + + "637265656e20776f756c642062652069742e")); + }}; + + public static final List aeadTestList = + new LinkedList() {{ + add(new TestData("RFC 7539 Sample AEAD Test Vector", + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "070000004041424344454647", + 1, Cipher.ENCRYPT_MODE, + "4c616469657320616e642047656e746c656d656e206f662074686520636c6173" + + "73206f66202739393a204966204920636f756c64206f6666657220796f75206f" + + "6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" + + "637265656e20776f756c642062652069742e", + "50515253c0c1c2c3c4c5c6c7", + "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" + + "3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" + + "92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" + + "3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd060" + + "0691")); + add(new TestData("RFC 7539 A.5 Sample Decryption", + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "000000000102030405060708", + 1, Cipher.DECRYPT_MODE, + "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb2" + + "4c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf" + + "332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c855" + + "9797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4" + + "b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523e" + + "af4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a" + + "0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a10" + + "49e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29" + + "a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38", + "f33388860000000000004e91", + "496e7465726e65742d4472616674732061726520647261667420646f63756d65" + + "6e74732076616c696420666f722061206d6178696d756d206f6620736978206d" + + "6f6e74687320616e64206d617920626520757064617465642c207265706c6163" + + "65642c206f72206f62736f6c65746564206279206f7468657220646f63756d65" + + "6e747320617420616e792074696d652e20497420697320696e617070726f7072" + + "6961746520746f2075736520496e7465726e65742d4472616674732061732072" + + "65666572656e6365206d6174657269616c206f7220746f206369746520746865" + + "6d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67" + + "726573732e2fe2809d")); + }}; + + /** + * Make sure we do not use this Cipher object without initializing it + * at all + */ + public static final TestMethod noInitTest = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return true; // Valid for all algs + } + + @Override + public boolean run(String algorithm) { + System.out.println("----- No Init Test [" + algorithm + + "] -----"); + try { + Cipher cipher = Cipher.getInstance(algorithm); + TestData testData; + switch (algorithm) { + case ALG_CC20: + testData = testList.get(0); + break; + case ALG_CC20_P1305: + testData = aeadTestList.get(0); + break; + default: + throw new IllegalArgumentException( + "Unsupported cipher type: " + algorithm); + } + + // Attempting to use the cipher without initializing it + // should throw an IllegalStateException + try { + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + throw new RuntimeException( + "Expected IllegalStateException not thrown"); + } catch (IllegalStateException ise) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + /** + * Make sure we don't allow a double init using the same parameters + */ + public static final TestMethod doubleInitTest = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return true; // Valid for all algs + } + + @Override + public boolean run(String algorithm) { + System.out.println("----- Double Init Test [" + algorithm + + "] -----"); + try { + AlgorithmParameterSpec spec; + Cipher cipher = Cipher.getInstance(algorithm); + TestData testData; + switch (algorithm) { + case ALG_CC20: + testData = testList.get(0); + spec = new ChaCha20ParameterSpec(testData.nonce, + testData.counter); + break; + case ALG_CC20_P1305: + testData = aeadTestList.get(0); + spec = new IvParameterSpec(testData.nonce); + break; + default: + throw new IllegalArgumentException( + "Unsupported cipher type: " + algorithm); + } + SecretKey key = new SecretKeySpec(testData.key, ALG_CC20); + + // Initialize the first time, this should work. + cipher.init(testData.direction, key, spec); + + // Immediately initializing a second time with the same + // parameters should fail + try { + cipher.init(testData.direction, key, spec); + throw new RuntimeException( + "Expected InvalidKeyException not thrown"); + } catch (InvalidKeyException ike) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + /** + * Attempt to run two full encryption operations without an init in + * between. + */ + public static final TestMethod encTwiceNoInit = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return true; // Valid for all algs + } + + @Override + public boolean run(String algorithm) { + System.out.println("----- Encrypt second time without init [" + + algorithm + "] -----"); + try { + AlgorithmParameterSpec spec; + Cipher cipher = Cipher.getInstance(algorithm); + TestData testData; + switch (algorithm) { + case ALG_CC20: + testData = testList.get(0); + spec = new ChaCha20ParameterSpec(testData.nonce, + testData.counter); + break; + case ALG_CC20_P1305: + testData = aeadTestList.get(0); + spec = new IvParameterSpec(testData.nonce); + break; + default: + throw new IllegalArgumentException( + "Unsupported cipher type: " + algorithm); + } + SecretKey key = new SecretKeySpec(testData.key, ALG_CC20); + + // Initialize and encrypt + cipher.init(testData.direction, key, spec); + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + System.out.println("First encryption complete"); + + // Now attempt to encrypt again without changing the key/IV + // This should fail. + try { + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + throw new RuntimeException( + "Expected IllegalStateException not thrown"); + } catch (IllegalStateException ise) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + /** + * Attempt to run two full decryption operations without an init in + * between. + */ + public static final TestMethod decTwiceNoInit = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return true; // Valid for all algs + } + + @Override + public boolean run(String algorithm) { + System.out.println("----- Decrypt second time without init [" + + algorithm + "] -----"); + try { + AlgorithmParameterSpec spec; + Cipher cipher = Cipher.getInstance(algorithm); + TestData testData; + switch (algorithm) { + case ALG_CC20: + testData = testList.get(1); + spec = new ChaCha20ParameterSpec(testData.nonce, + testData.counter); + break; + case ALG_CC20_P1305: + testData = aeadTestList.get(1); + spec = new IvParameterSpec(testData.nonce); + break; + default: + throw new IllegalArgumentException( + "Unsupported cipher type: " + algorithm); + } + SecretKey key = new SecretKeySpec(testData.key, ALG_CC20); + + // Initialize and encrypt + cipher.init(testData.direction, key, spec); + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + System.out.println("First decryption complete"); + + // Now attempt to encrypt again without changing the key/IV + // This should fail. + try { + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + throw new RuntimeException( + "Expected IllegalStateException not thrown"); + } catch (IllegalStateException ise) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + /** + * Perform an AEAD decryption with corrupted data so the tag does not + * match. Then attempt to reuse the cipher without initialization. + */ + public static final TestMethod decFailNoInit = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return algorithm.equals(ALG_CC20_P1305); + } + + @Override + public boolean run(String algorithm) { + System.out.println( + "----- Fail decryption, try again with no init [" + + algorithm + "] -----"); + try { + TestData testData = aeadTestList.get(1); + AlgorithmParameterSpec spec = + new IvParameterSpec(testData.nonce); + byte[] corruptInput = testData.input.clone(); + corruptInput[0]++; // Corrupt the ciphertext + SecretKey key = new SecretKeySpec(testData.key, ALG_CC20); + Cipher cipher = Cipher.getInstance(algorithm); + + try { + // Initialize and encrypt + cipher.init(testData.direction, key, spec); + cipher.updateAAD(testData.aad); + cipher.doFinal(corruptInput); + throw new RuntimeException( + "Expected AEADBadTagException not thrown"); + } catch (AEADBadTagException abte) { + System.out.println("Expected decryption failure occurred"); + } + + // Make sure that despite the exception, the Cipher object is + // not in a state that would leave it initialized and able + // to process future decryption operations without init. + try { + cipher.updateAAD(testData.aad); + cipher.doFinal(testData.input); + throw new RuntimeException( + "Expected IllegalStateException not thrown"); + } catch (IllegalStateException ise) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + /** + * Encrypt once successfully, then attempt to init with the same + * key and nonce. + */ + public static final TestMethod encTwiceInitSameParams = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return true; // Valid for all algs + } + + @Override + public boolean run(String algorithm) { + System.out.println("----- Encrypt, then init with same params [" + + algorithm + "] -----"); + try { + AlgorithmParameterSpec spec; + Cipher cipher = Cipher.getInstance(algorithm); + TestData testData; + switch (algorithm) { + case ALG_CC20: + testData = testList.get(0); + spec = new ChaCha20ParameterSpec(testData.nonce, + testData.counter); + break; + case ALG_CC20_P1305: + testData = aeadTestList.get(0); + spec = new IvParameterSpec(testData.nonce); + break; + default: + throw new IllegalArgumentException( + "Unsupported cipher type: " + algorithm); + } + SecretKey key = new SecretKeySpec(testData.key, ALG_CC20); + + // Initialize then encrypt + cipher.init(testData.direction, key, spec); + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + System.out.println("First encryption complete"); + + // Initializing after the completed encryption with + // the same key and nonce should fail. + try { + cipher.init(testData.direction, key, spec); + throw new RuntimeException( + "Expected InvalidKeyException not thrown"); + } catch (InvalidKeyException ike) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + /** + * Decrypt once successfully, then attempt to init with the same + * key and nonce. + */ + public static final TestMethod decTwiceInitSameParams = new TestMethod() { + @Override + public boolean isValid(String algorithm) { + return true; // Valid for all algs + } + + @Override + public boolean run(String algorithm) { + System.out.println("----- Decrypt, then init with same params [" + + algorithm + "] -----"); + try { + AlgorithmParameterSpec spec; + Cipher cipher = Cipher.getInstance(algorithm); + TestData testData; + switch (algorithm) { + case ALG_CC20: + testData = testList.get(1); + spec = new ChaCha20ParameterSpec(testData.nonce, + testData.counter); + break; + case ALG_CC20_P1305: + testData = aeadTestList.get(1); + spec = new IvParameterSpec(testData.nonce); + break; + default: + throw new IllegalArgumentException( + "Unsupported cipher type: " + algorithm); + } + SecretKey key = new SecretKeySpec(testData.key, ALG_CC20); + + // Initialize then decrypt + cipher.init(testData.direction, key, spec); + if (algorithm.equals(ALG_CC20_P1305)) { + cipher.updateAAD(testData.aad); + } + cipher.doFinal(testData.input); + System.out.println("First decryption complete"); + + // Initializing after the completed decryption with + // the same key and nonce should fail. + try { + cipher.init(testData.direction, key, spec); + throw new RuntimeException( + "Expected InvalidKeyException not thrown"); + } catch (InvalidKeyException ike) { + // Do nothing, this is what we expected to happen + } + } catch (Exception exc) { + System.out.println("Unexpected exception: " + exc); + exc.printStackTrace(); + return false; + } + + return true; + } + }; + + public static final List algList = + Arrays.asList(ALG_CC20, ALG_CC20_P1305); + + public static final List testMethodList = + Arrays.asList(noInitTest, doubleInitTest, encTwiceNoInit, + decTwiceNoInit, decFailNoInit, encTwiceInitSameParams, + decTwiceInitSameParams); + + public static void main(String args[]) throws Exception { + int testsPassed = 0; + int testNumber = 0; + + for (TestMethod tm : testMethodList) { + for (String alg : algList) { + if (tm.isValid(alg)) { + testNumber++; + boolean result = tm.run(alg); + System.out.println("Result: " + (result ? "PASS" : "FAIL")); + if (result) { + testsPassed++; + } + } + } + } + + System.out.println("Total Tests: " + testNumber + + ", Tests passed: " + testsPassed); + if (testsPassed < testNumber) { + throw new RuntimeException( + "Not all tests passed. See output for failure info"); + } + } +} + diff -r d66751750b72 -r c10dbcaed048 test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/ChaCha20Poly1305ParamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/ChaCha20Poly1305ParamTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8153029 + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main ChaCha20Poly1305ParamTest + * @summary ChaCha20 Cipher Implementation (parameters) + */ + +import java.util.*; +import java.io.IOException; +import java.security.GeneralSecurityException; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.ChaCha20ParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.AEADBadTagException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.AlgorithmParameters; +import java.security.NoSuchAlgorithmException; +import java.nio.ByteBuffer; +import jdk.test.lib.Convert; + +public class ChaCha20Poly1305ParamTest { + public static class TestData { + public TestData(String name, String keyStr, String nonceStr, int ctr, + int dir, String inputStr, String aadStr, String outStr) { + testName = Objects.requireNonNull(name); + key = Convert.hexStringToByteArray(Objects.requireNonNull(keyStr)); + nonce = Convert.hexStringToByteArray( + Objects.requireNonNull(nonceStr)); + if ((counter = ctr) < 0) { + throw new IllegalArgumentException( + "counter must be 0 or greater"); + } + direction = dir; + if ((direction != Cipher.ENCRYPT_MODE) && + (direction != Cipher.DECRYPT_MODE)) { + throw new IllegalArgumentException( + "Direction must be ENCRYPT_MODE or DECRYPT_MODE"); + } + input = Convert.hexStringToByteArray( + Objects.requireNonNull(inputStr)); + aad = (aadStr != null) ? + Convert.hexStringToByteArray(aadStr) : null; + expOutput = Convert.hexStringToByteArray( + Objects.requireNonNull(outStr)); + } + + public final String testName; + public final byte[] key; + public final byte[] nonce; + public final int counter; + public final int direction; + public final byte[] input; + public final byte[] aad; + public final byte[] expOutput; + } + + public static final List aeadTestList = + new LinkedList() {{ + add(new TestData("RFC 7539 Sample AEAD Test Vector", + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "070000004041424344454647", + 1, Cipher.ENCRYPT_MODE, + "4c616469657320616e642047656e746c656d656e206f662074686520636c6173" + + "73206f66202739393a204966204920636f756c64206f6666657220796f75206f" + + "6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" + + "637265656e20776f756c642062652069742e", + "50515253c0c1c2c3c4c5c6c7", + "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" + + "3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" + + "92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" + + "3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd060" + + "0691")); + add(new TestData("RFC 7539 A.5 Sample Decryption", + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "000000000102030405060708", + 1, Cipher.DECRYPT_MODE, + "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb2" + + "4c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf" + + "332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c855" + + "9797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4" + + "b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523e" + + "af4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a" + + "0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a10" + + "49e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29" + + "a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38", + "f33388860000000000004e91", + "496e7465726e65742d4472616674732061726520647261667420646f63756d65" + + "6e74732076616c696420666f722061206d6178696d756d206f6620736978206d" + + "6f6e74687320616e64206d617920626520757064617465642c207265706c6163" + + "65642c206f72206f62736f6c65746564206279206f7468657220646f63756d65" + + "6e747320617420616e792074696d652e20497420697320696e617070726f7072" + + "6961746520746f2075736520496e7465726e65742d4472616674732061732072" + + "65666572656e6365206d6174657269616c206f7220746f206369746520746865" + + "6d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67" + + "726573732e2fe2809d")); + }}; + + // 12-byte nonce DER-encoded as an OCTET_STRING + public static final byte[] NONCE_OCTET_STR_12 = { + 4, 12, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 + }; + + // Invalid 16-byte nonce DER-encoded as an OCTET_STRING + public static final byte[] NONCE_OCTET_STR_16 = { + 4, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }; + + // Throwaway key for default init tests + public static final SecretKey DEF_KEY = new SecretKeySpec(new byte[] + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + }, "ChaCha20"); + + public static void main(String args[]) throws Exception { + int testsPassed = 0; + int testNumber = 0; + + // Try some default initializations + testDefaultAlgParams("ChaCha20", Cipher.ENCRYPT_MODE, true); + testDefaultAlgParams("ChaCha20-Poly1305", Cipher.ENCRYPT_MODE, true); + testDefaultAlgParamSpec("ChaCha20", Cipher.ENCRYPT_MODE, true); + testDefaultAlgParamSpec("ChaCha20-Poly1305", Cipher.ENCRYPT_MODE, true); + testDefaultAlgParams("ChaCha20", Cipher.DECRYPT_MODE, false); + testDefaultAlgParams("ChaCha20-Poly1305", Cipher.DECRYPT_MODE, false); + testDefaultAlgParamSpec("ChaCha20", Cipher.DECRYPT_MODE, false); + testDefaultAlgParamSpec("ChaCha20-Poly1305", Cipher.DECRYPT_MODE, + false); + + // Try (and hopefully fail) to create a ChaCha20 AlgorithmParameterSpec + System.out.println( + "*** Test: Try to make ChaCha20 AlgorithmParameterSpec"); + try { + ChaCha20ParameterSpec badChaCha20Spec = + new ChaCha20ParameterSpec(NONCE_OCTET_STR_16, 1); + throw new RuntimeException("ChaCha20 AlgorithmParameterSpec " + + "with 16 byte nonce should fail"); + } catch (IllegalArgumentException iae) { + System.out.println("Caught expected exception: " + iae); + } + + // Try (and hopefully fail) to create a ChaCha20 AlgorithmParameters + System.out.println( + "*** Test: Try to make ChaCha20 AlgorithmParameters"); + try { + AlgorithmParameters apsNoChaCha20 = + AlgorithmParameters.getInstance("ChaCha20"); + throw new RuntimeException( + "ChaCha20 AlgorithmParameters should fail"); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Caught expected exception: " + nsae); + } + + // Create the AlgorithmParameters object from a valid encoding + System.out.println("*** Test: Create and init ChaCha20-Poly1305 APS"); + AlgorithmParameters apsGood = + AlgorithmParameters.getInstance("ChaCha20-Poly1305"); + apsGood.init(NONCE_OCTET_STR_12); + System.out.println("Test Passed"); + + // Pull an AlgorithmParameters object out of the initialized cipher + // and compare its value against the original. + System.out.println("*** Test: Init ChaCha20-Poly1305 Cipher using " + + "AP, retrieve AP and compare"); + Cipher cc20p1305 = Cipher.getInstance("ChaCha20-Poly1305"); + cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY, apsGood); + AlgorithmParameters pulledParams = cc20p1305.getParameters(); + byte[] apsGoodData = apsGood.getEncoded(); + byte[] pulledParamsData = pulledParams.getEncoded(); + if (!Arrays.equals(apsGoodData, pulledParamsData)) { + throw new RuntimeException( + "Retrieved parameters do not match those used to init cipher"); + } + System.out.println("Test Passed"); + + // Try the same test with ChaCha20. It should always be null. + System.out.println("*** Test: Init ChaCha20 Cipher using " + + "AP, retrieve AP and compare"); + Cipher cc20 = Cipher.getInstance("ChaCha20"); + cc20.init(Cipher.ENCRYPT_MODE, DEF_KEY); + pulledParams = cc20.getParameters(); + if (pulledParams != null) { + throw new RuntimeException("Unexpected non-null " + + "AlgorithmParameters from ChaCha20 cipiher"); + } + System.out.println("Test Passed"); + + // Create and try to init using invalid encoding + AlgorithmParameters apsBad = + AlgorithmParameters.getInstance("ChaCha20-Poly1305"); + System.out.println("*** Test: Use invalid encoding scheme"); + try { + apsBad.init(NONCE_OCTET_STR_12, "OraclePrivate"); + throw new RuntimeException("Allowed unsupported encoding scheme: " + + apsBad.getAlgorithm()); + } catch (IOException iae) { + System.out.println("Caught expected exception: " + iae); + } + + // Try to init using supported scheme but invalid length + System.out.println("*** Test: Use supported scheme, nonce too large"); + try { + apsBad.init(NONCE_OCTET_STR_16, "ASN.1"); + throw new RuntimeException("Allowed invalid encoded length"); + } catch (IOException ioe) { + System.out.println("Caught expected exception: " + ioe); + } + + System.out.println("----- AEAD Tests -----"); + for (TestData test : aeadTestList) { + System.out.println("*** Test " + ++testNumber + ": " + + test.testName); + if (runAEADTest(test)) { + testsPassed++; + } + } + System.out.println(); + + System.out.println("Total tests: " + testNumber + + ", Passed: " + testsPassed + ", Failed: " + + (testNumber - testsPassed)); + if (testsPassed != testNumber) { + throw new RuntimeException("One or more tests failed. " + + "Check output for details"); + } + } + + /** + * Attempt default inits with null AlgorithmParameters + * + * @param alg the algorithm (ChaCha20, ChaCha20-Poly1305) + * @param mode the Cipher mode (ENCRYPT_MODE, etc.) + */ + private static void testDefaultAlgParams(String alg, int mode, + boolean shouldPass) { + byte[] ivOne = null, ivTwo = null; + System.out.println("Test default AlgorithmParameters: Cipher = " + + alg + ", mode = " + mode); + try { + AlgorithmParameters params = null; + Cipher cipher = Cipher.getInstance(alg); + cipher.init(mode, DEF_KEY, params, null); + ivOne = cipher.getIV(); + cipher.init(mode, DEF_KEY, params, null); + ivTwo = cipher.getIV(); + if (!shouldPass) { + throw new RuntimeException( + "Did not receive expected exception"); + } + } catch (GeneralSecurityException gse) { + if (shouldPass) { + throw new RuntimeException(gse); + } + System.out.println("Caught expected exception: " + gse); + return; + } + if (Arrays.equals(ivOne, ivTwo)) { + throw new RuntimeException( + "FAIL! Two inits generated same nonces"); + } else { + System.out.println("IV 1:\n" + dumpHexBytes(ivOne, 16, "\n", " ")); + System.out.println("IV 1:\n" + dumpHexBytes(ivTwo, 16, "\n", " ")); + } + } + + /** + * Attempt default inits with null AlgorithmParameters + * + * @param alg the algorithm (ChaCha20, ChaCha20-Poly1305) + * @param mode the Cipher mode (ENCRYPT_MODE, etc.) + */ + private static void testDefaultAlgParamSpec(String alg, int mode, + boolean shouldPass) { + byte[] ivOne = null, ivTwo = null; + System.out.println("Test default AlgorithmParameterSpec: Cipher = " + + alg + ", mode = " + mode); + try { + AlgorithmParameterSpec params = null; + Cipher cipher = Cipher.getInstance(alg); + cipher.init(mode, DEF_KEY, params, null); + ivOne = cipher.getIV(); + cipher.init(mode, DEF_KEY, params, null); + ivTwo = cipher.getIV(); + if (!shouldPass) { + throw new RuntimeException( + "Did not receive expected exception"); + } + } catch (GeneralSecurityException gse) { + if (shouldPass) { + throw new RuntimeException(gse); + } + System.out.println("Caught expected exception: " + gse); + return; + } + if (Arrays.equals(ivOne, ivTwo)) { + throw new RuntimeException( + "FAIL! Two inits generated same nonces"); + } else { + System.out.println("IV 1:\n" + dumpHexBytes(ivOne, 16, "\n", " ")); + System.out.println("IV 2:\n" + dumpHexBytes(ivTwo, 16, "\n", " ")); + } + } + + private static boolean runAEADTest(TestData testData) + throws GeneralSecurityException, IOException { + boolean result = false; + + Cipher mambo = Cipher.getInstance("ChaCha20-Poly1305"); + SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20"); + AlgorithmParameters mamboParams = + AlgorithmParameters.getInstance("ChaCha20-Poly1305"); + + // Put the nonce into ASN.1 ChaCha20-Poly1305 parameter format + byte[] derNonce = new byte[testData.nonce.length + 2]; + derNonce[0] = 0x04; + derNonce[1] = (byte)testData.nonce.length; + System.arraycopy(testData.nonce, 0, derNonce, 2, + testData.nonce.length); + mamboParams.init(derNonce); + + mambo.init(testData.direction, mamboKey, mamboParams); + + byte[] out = new byte[mambo.getOutputSize(testData.input.length)]; + int outOff = 0; + try { + mambo.updateAAD(testData.aad); + outOff += mambo.update(testData.input, 0, testData.input.length, + out, outOff); + outOff += mambo.doFinal(out, outOff); + } catch (AEADBadTagException abte) { + // If we get a bad tag or derive a tag mismatch, log it + // and register it as a failure + System.out.println("FAIL: " + abte); + return false; + } + + if (!Arrays.equals(out, testData.expOutput)) { + System.out.println("ERROR - Output Mismatch!"); + System.out.println("Expected:\n" + + dumpHexBytes(testData.expOutput, 16, "\n", " ")); + System.out.println("Actual:\n" + + dumpHexBytes(out, 16, "\n", " ")); + System.out.println(); + } else { + result = true; + } + + return result; + } + + /** + * Dump the hex bytes of a buffer into string form. + * + * @param data The array of bytes to dump to stdout. + * @param itemsPerLine The number of bytes to display per line + * if the {@code lineDelim} character is blank then all bytes + * will be printed on a single line. + * @param lineDelim The delimiter between lines + * @param itemDelim The delimiter between bytes + * + * @return The hexdump of the byte array + */ + private static String dumpHexBytes(byte[] data, int itemsPerLine, + String lineDelim, String itemDelim) { + return dumpHexBytes(ByteBuffer.wrap(data), itemsPerLine, lineDelim, + itemDelim); + } + + private static String dumpHexBytes(ByteBuffer data, int itemsPerLine, + String lineDelim, String itemDelim) { + StringBuilder sb = new StringBuilder(); + if (data != null) { + data.mark(); + int i = 0; + while (data.remaining() > 0) { + if (i % itemsPerLine == 0 && i != 0) { + sb.append(lineDelim); + } + sb.append(String.format("%02X", data.get())).append(itemDelim); + i++; + } + data.reset(); + } + + return sb.toString(); + } +} + diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java --- a/test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java Thu May 31 13:39:26 2018 -0700 @@ -42,6 +42,8 @@ import java.util.Arrays; import java.util.List; +import static java.lang.invoke.MethodType.methodType; + import static org.junit.Assert.*; public class MethodHandlesInsertArgumentsTest extends MethodHandlesTest { @@ -88,4 +90,43 @@ System.out.println("result: "+res2List); assertEquals(resList, res2List); } + + private static MethodHandle methodHandle = null; + static { + try { + methodHandle = MethodHandles.lookup().findVirtual( + MethodHandlesInsertArgumentsTest.class, + "testMethod", + methodType(void.class, String.class, String.class)); + } catch(ReflectiveOperationException ex) { + throw new InternalError(ex); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertArgumentsInvalidPos() { + countTest(); + MethodHandles.insertArguments(methodHandle, -1, "First", "Second"); + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertArgumentsTooManyParams() { + countTest(); + MethodHandles.insertArguments(methodHandle, 1, "First", "Second", "Third"); + } + + @Test(expected = ClassCastException.class) + public void testInsertArgumentsPosZero() { + countTest(); + MethodHandles.insertArguments(methodHandle, 0, "First"); + } + + @Test(expected = ClassCastException.class) + public void testInsertArgumentsIncorrectParam() { + countTest(); + MethodHandles.insertArguments(methodHandle, 1, "First", new Object()); + } + + void testMethod(String a, String b) { + } } diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/net/SocketOption/TcpKeepAliveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/net/SocketOption/TcpKeepAliveTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8194298 + * @summary Add support for per Socket configuration of TCP keepalive + * @modules jdk.net + * @run main TcpKeepAliveTest + */ +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.MulticastSocket; +import java.net.ServerSocket; +import java.net.Socket; +import jdk.net.ExtendedSocketOptions; + +public class TcpKeepAliveTest { + + private static final String LOCAL_HOST = "127.0.0.1"; + private static final int DEFAULT_KEEP_ALIVE_PROBES = 7; + private static final int DEFAULT_KEEP_ALIVE_TIME = 1973; + private static final int DEFAULT_KEEP_ALIVE_INTVL = 53; + + public static void main(String args[]) throws IOException { + + try (ServerSocket ss = new ServerSocket(0); + Socket s = new Socket(LOCAL_HOST, ss.getLocalPort()); + DatagramSocket ds = new DatagramSocket(0); + MulticastSocket mc = new MulticastSocket(0)) { + if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + ss.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + if (ss.getOption(ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME); + } + } + if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + ss.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + if (ss.getOption(ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES); + } + } + if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + ss.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + if (ss.getOption(ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL); + } + } + if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + s.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + if (s.getOption(ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME); + } + } + if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + s.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + if (s.getOption(ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES); + } + } + if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + s.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + if (s.getOption(ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL); + } + } + if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT is applicable" + + " for TCP Sockets only."); + } + if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE is applicable" + + " for TCP Sockets only."); + } + if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL is applicable" + + " for TCP Sockets only."); + } + if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT is applicable" + + " for TCP Sockets only"); + } + if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE is applicable" + + " for TCP Sockets only"); + } + if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL is applicable" + + " for TCP Sockets only"); + } + } + } +} diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/nio/channels/AsynchronousServerSocketChannel/Basic.java --- a/test/jdk/java/nio/channels/AsynchronousServerSocketChannel/Basic.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/java/nio/channels/AsynchronousServerSocketChannel/Basic.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* @test * @bug 4607272 6842687 * @summary Unit test for AsynchronousServerSocketChannel + * @modules jdk.net * @run main/timeout=180 Basic */ @@ -31,10 +32,14 @@ import java.net.*; import static java.net.StandardSocketOptions.*; import java.io.IOException; +import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPCOUNT; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPINTERVAL; public class Basic { @@ -166,6 +171,16 @@ ch.setOption(SO_REUSEPORT, false); checkOption(ch, SO_REUSEPORT, false); } + List extOptions = List.of(TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + if (options.containsAll(extOptions)) { + ch.setOption(TCP_KEEPIDLE, 1234); + checkOption(ch, TCP_KEEPIDLE, 1234); + ch.setOption(TCP_KEEPINTERVAL, 123); + checkOption(ch, TCP_KEEPINTERVAL, 123); + ch.setOption(TCP_KEEPCOUNT, 7); + checkOption(ch, TCP_KEEPCOUNT, 7); + } } finally { ch.close(); } diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java --- a/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java Thu May 31 13:39:26 2018 -0700 @@ -25,9 +25,10 @@ * @bug 4607272 6842687 6878369 6944810 7023403 * @summary Unit test for AsynchronousSocketChannel(use -Dseed=X to set PRNG seed) * @library /test/lib + * @modules jdk.net + * @key randomness intermittent * @build jdk.test.lib.RandomFactory jdk.test.lib.Utils * @run main/othervm/timeout=600 Basic -skipSlowConnectTest - * @key randomness intermittent */ import java.io.Closeable; @@ -41,6 +42,10 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; import jdk.test.lib.RandomFactory; +import java.util.List; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPCOUNT; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPINTERVAL; public class Basic { private static final Random RAND = RandomFactory.getRandom(); @@ -183,9 +188,26 @@ if (!ch.setOption(SO_REUSEPORT, true).getOption(SO_REUSEPORT)) throw new RuntimeException("SO_REUSEPORT did not change"); } + List extOptions = List.of(TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + if (options.containsAll(extOptions)) { + ch.setOption(TCP_KEEPIDLE, 1234); + checkOption(ch, TCP_KEEPIDLE, 1234); + ch.setOption(TCP_KEEPINTERVAL, 123); + checkOption(ch, TCP_KEEPINTERVAL, 123); + ch.setOption(TCP_KEEPCOUNT, 7); + checkOption(ch, TCP_KEEPCOUNT, 7); + } } } + static void checkOption(AsynchronousSocketChannel sc, SocketOption name, Object expectedValue) + throws IOException { + Object value = sc.getOption(name); + if (!value.equals(expectedValue)) { + throw new RuntimeException("value not as expected"); + } + } static void testConnect() throws Exception { System.out.println("-- connect --"); diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/nio/channels/Selector/SelectAndClose.java --- a/test/jdk/java/nio/channels/Selector/SelectAndClose.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/java/nio/channels/Selector/SelectAndClose.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,63 +22,68 @@ */ /* @test - * @bug 5004077 + * @bug 5004077 8203765 * @summary Check blocking of select and close */ -import java.nio.channels.*; import java.io.IOException; -import java.util.concurrent.CountDownLatch; +import java.lang.management.ManagementFactory; +import java.lang.management.MonitorInfo; +import java.lang.management.ThreadInfo; +import java.nio.channels.Selector; public class SelectAndClose { static Selector selector; static volatile boolean awakened = false; - static volatile boolean closed = false; + + private static boolean mightHoldLock(Thread t, Object lock) { + long tid = t.getId(); + int hash = System.identityHashCode(lock); + ThreadInfo ti = ManagementFactory.getThreadMXBean(). + getThreadInfo(new long[]{ tid} , true, false, 100)[0]; + if (ti != null) { + for (MonitorInfo mi : ti.getLockedMonitors()) { + if (mi.getIdentityHashCode() == hash) + return true; + } + } + return false; + } public static void main(String[] args) throws Exception { selector = Selector.open(); // Create and start a selector in a separate thread. - final CountDownLatch selectLatch = new CountDownLatch(1); - new Thread(new Runnable() { + Thread selectThread = new Thread(new Runnable() { public void run() { try { - selectLatch.countDown(); selector.select(); awakened = true; } catch (IOException e) { - System.err.println(e); - } - } - }).start(); - - // Wait for above thread to get to select() before we call close. - selectLatch.await(); - Thread.sleep(2000); - - // Try to close. This should wakeup select. - Thread closeThread = new Thread(new Runnable() { - public void run() { - try { - selector.close(); - closed = true; - } catch (IOException e) { - System.err.println(e); + e.printStackTrace(); } } }); - closeThread.start(); + selectThread.start(); - // Wait for select() to be awakened, which should be done by close. - closeThread.join(); + // Spin until the monitor of the selected-key set is likely held + // as selected operations are specified to synchronize on the + // selected-key set. + while (!mightHoldLock(selectThread, selector.selectedKeys())) { + Thread.sleep(50); + } + + // Close the selector. + selector.close(); if (!awakened) selector.wakeup(); - // Correct result is true and true - if (!awakened) - throw new RuntimeException("Select did not wake up"); - if (!closed) - throw new RuntimeException("Selector did not close"); + // Wait for select() thread to finish. + selectThread.join(); + + if (!awakened) { + throw new RuntimeException("Select did not awaken!"); + } } } diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/nio/channels/ServerSocketChannel/SocketOptionTests.java --- a/test/jdk/java/nio/channels/ServerSocketChannel/SocketOptionTests.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/java/nio/channels/ServerSocketChannel/SocketOptionTests.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,25 @@ * @bug 4640544 8044773 * @summary Unit test for ServerSocketChannel setOption/getOption/options * methods. + * @modules jdk.net * @requires !vm.graal.enabled * @run main SocketOptionTests * @run main/othervm --limit-modules=java.base SocketOptionTests */ -import java.nio.*; import java.nio.channels.*; import java.net.*; import java.io.IOException; import java.util.*; import static java.net.StandardSocketOptions.*; +import static jdk.net.ExtendedSocketOptions.*; public class SocketOptionTests { + private static final int DEFAULT_KEEP_ALIVE_PROBES = 7; + private static final int DEFAULT_KEEP_ALIVE_TIME = 1973; + private static final int DEFAULT_KEEP_ALIVE_INTVL = 53; + static void checkOption(ServerSocketChannel ssc, SocketOption name, Object expectedValue) throws IOException { @@ -76,6 +81,16 @@ ssc.setOption(SO_REUSEPORT, false); checkOption(ssc, SO_REUSEPORT, false); } + if (ssc.supportedOptions().containsAll(List.of(TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL))) { + ssc.setOption(TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + checkOption(ssc, TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + ssc.setOption(TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + checkOption(ssc, TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + ssc.setOption(TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + checkOption(ssc, TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + + } // NullPointerException try { diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/nio/channels/SocketChannel/SocketOptionTests.java --- a/test/jdk/java/nio/channels/SocketChannel/SocketOptionTests.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/java/nio/channels/SocketChannel/SocketOptionTests.java Thu May 31 13:39:26 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,21 @@ * @bug 4640544 8044773 * @summary Unit test to check SocketChannel setOption/getOption/options * methods. + * @modules java.base/sun.net.ext + * jdk.net * @requires !vm.graal.enabled * @run main SocketOptionTests * @run main/othervm --limit-modules=java.base SocketOptionTests */ -import java.nio.*; import java.nio.channels.*; import java.net.*; import java.io.IOException; import java.util.*; import static java.net.StandardSocketOptions.*; +import static jdk.net.ExtendedSocketOptions.*; +import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM; +import sun.net.ext.ExtendedSocketOptions; public class SocketOptionTests { @@ -52,8 +56,20 @@ // check supported options Set> options = sc.supportedOptions(); - List expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, - SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, TCP_NODELAY); + + List extOptions = List.of(TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + List expected; + boolean keepAliveOptsupported; + if (keepAliveOptsupported=ExtendedSocketOptions.options(SOCK_STREAM) + .containsAll(extOptions)) { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE, + SO_REUSEADDR, SO_LINGER, TCP_NODELAY, TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + } else { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE, + SO_REUSEADDR, SO_LINGER, TCP_NODELAY); + } for (SocketOption opt: expected) { if (!options.contains(opt)) throw new RuntimeException(opt.name() + " should be supported"); @@ -117,7 +133,14 @@ throw new RuntimeException("expected linger to be disabled"); sc.setOption(TCP_NODELAY, true); // can't check sc.setOption(TCP_NODELAY, false); // can't check - + if (keepAliveOptsupported) { + sc.setOption(TCP_KEEPIDLE, 1234); + checkOption(sc, TCP_KEEPIDLE, 1234); + sc.setOption(TCP_KEEPINTERVAL, 123); + checkOption(sc, TCP_KEEPINTERVAL, 123); + sc.setOption(TCP_KEEPCOUNT, 7); + checkOption(sc, TCP_KEEPCOUNT, 7); + } // NullPointerException try { sc.setOption(null, "value"); diff -r d66751750b72 -r c10dbcaed048 test/jdk/java/util/function/PredicateNotTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/util/function/PredicateNotTest.java Thu May 31 13:39:26 2018 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8050818 + * @run testng PredicateNotTest + */ + +import java.util.List; +import java.util.function.Predicate; +import org.testng.annotations.Test; +import static java.util.function.Predicate.not; +import static java.util.stream.Collectors.joining; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +@Test(groups = "unit") +public class PredicateNotTest { + static class IsEmptyPredicate implements Predicate { + @Override + public boolean test(String s) { + return s.isEmpty(); + } + } + + public void test() { + List test = List.of( + "A non-empty line", + "", + "A non-empty line", + "", + "A non-empty line", + "", + "A non-empty line", + "" + ); + String expected = "A non-empty line\nA non-empty line\nA non-empty line\nA non-empty line"; + + assertEquals(test.stream().filter(not(String::isEmpty)).collect(joining("\n")), expected); + assertEquals(test.stream().filter(not(s -> s.isEmpty())).collect(joining("\n")), expected); + assertEquals(test.stream().filter(not(new IsEmptyPredicate())).collect(joining("\n")), expected); + assertEquals(test.stream().filter(not(not(not(String::isEmpty)))).collect(joining("\n")), expected); + assertEquals(test.stream().filter(not(not(not(s -> s.isEmpty())))).collect(joining("\n")), expected); + assertEquals(test.stream().filter(not(not(not(new IsEmptyPredicate())))).collect(joining("\n")), expected); + } +} + diff -r d66751750b72 -r c10dbcaed048 test/jdk/lib/security/cacerts/VerifyCACerts.java --- a/test/jdk/lib/security/cacerts/VerifyCACerts.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jdk/lib/security/cacerts/VerifyCACerts.java Thu May 31 13:39:26 2018 -0700 @@ -19,11 +19,12 @@ * Please 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 8189131 8198240 8191844 + * @bug 8189131 8198240 8191844 8189949 * @requires java.runtime.name ~= "OpenJDK.*" * @summary Check root CA entries in cacerts file */ @@ -41,7 +42,7 @@ + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. - private static final int COUNT = 79; + private static final int COUNT = 78; // map of cert alias to SHA-256 fingerprint private static final Map FINGERPRINT_MAP @@ -89,8 +90,6 @@ "80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16"); put("baltimorecybertrustca [jdk]", "16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB"); - put("baltimorecodesigningca [jdk]", - "A9:15:45:DB:D2:E1:9C:4C:CD:F9:09:AA:71:90:0D:18:C7:35:1C:89:B3:15:F0:F1:3D:05:C1:3A:8F:FB:46:87"); put("digicertglobalrootca [jdk]", "43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61"); put("digicertglobalrootg2 [jdk]", diff -r d66751750b72 -r c10dbcaed048 test/jtreg-ext/requires/VMProps.java --- a/test/jtreg-ext/requires/VMProps.java Wed May 30 11:36:46 2018 -0700 +++ b/test/jtreg-ext/requires/VMProps.java Thu May 31 13:39:26 2018 -0700 @@ -80,6 +80,7 @@ map.put("vm.graal.enabled", isGraalEnabled()); map.put("docker.support", dockerSupport()); vmGC(map); // vm.gc.X = true/false + vmOptFinalFlags(map); VMProps.dump(map); return map; @@ -236,6 +237,25 @@ } /** + * Selected final flag. + * @param map - property-value pairs + * @param flagName - flag name + */ + private void vmOptFinalFlag(Map map, String flagName) { + String value = WB.getBooleanVMFlag(flagName) ? "true" : "false"; + map.put("vm.opt.final." + flagName, value); + } + + /** + * Selected sets of final flags. + * @param map -property-value pairs + */ + protected void vmOptFinalFlags(Map map) { + vmOptFinalFlag(map, "ClassUnloading"); + vmOptFinalFlag(map, "UseCompressedOops"); + } + + /** * @return true if VM runs RTM supported OS and false otherwise. */ protected String vmRTMOS() {