# HG changeset patch # User hseigel # Date 1427635275 14400 # Node ID cdecfa325d0cad39add94ead45a247d7f1430900 # Parent f07d88b6243cfc9ff827ed83baa084db8d8990db# Parent 838a9156720c68d276139b3677af8c17beb6ec65 Merge diff -r f07d88b6243c -r cdecfa325d0c .hgtags --- a/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -297,3 +297,4 @@ d6224d6021459ac8b3832e822f5acc849fa944af jdk9-b52 874d76e4699dfcd61ae1826c9fe0ddc1610ad598 jdk9-b53 82cd31c5d6ca8d4c1653f4eb1c09eb2d9a3b2813 jdk9-b54 +c97e2d1bad9708d379793ba2a4c848eda14c741e jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c .hgtags-top-repo --- a/.hgtags-top-repo Wed Mar 25 15:22:45 2015 +0000 +++ b/.hgtags-top-repo Sun Mar 29 09:21:15 2015 -0400 @@ -297,3 +297,4 @@ 1822e59f17121b09e7899cf338cfb6e37fe5fceb jdk9-b52 d6ed47125a76cd1cf8a100568507bfb5e9669d9f jdk9-b53 cb7367141e910e265b8344a8facee740bd1e5467 jdk9-b54 +0c37a832458f0e0b7d2a3f1a6f69aeae311aeb18 jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c common/autoconf/configure.ac --- a/common/autoconf/configure.ac Wed Mar 25 15:22:45 2015 +0000 +++ b/common/autoconf/configure.ac Sun Mar 29 09:21:15 2015 -0400 @@ -54,6 +54,7 @@ AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK]) AC_DEFUN_ONCE([CUSTOM_LATE_HOOK]) +AC_DEFUN_ONCE([CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK]) AC_DEFUN_ONCE([CUSTOM_SUMMARY_AND_WARNINGS_HOOK]) # This line needs to be here, verbatim, after all includes and the dummy hook @@ -265,6 +266,7 @@ # Create the actual output files. Now the main work of configure is done. AC_OUTPUT +CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK # Try to move the config.log file to the output directory. if test -e ./config.log; then diff -r f07d88b6243c -r cdecfa325d0c common/autoconf/flags.m4 --- a/common/autoconf/flags.m4 Wed Mar 25 15:22:45 2015 +0000 +++ b/common/autoconf/flags.m4 Sun Mar 29 09:21:15 2015 -0400 @@ -481,9 +481,8 @@ CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" fi if test "x$CFLAGS" != "x${ADDED_CFLAGS}"; then @@ -762,6 +761,8 @@ elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -liconv -bexpall -bernotok" fi # Customize LDFLAGS for executables diff -r f07d88b6243c -r cdecfa325d0c common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Wed Mar 25 15:22:45 2015 +0000 +++ b/common/autoconf/generated-configure.sh Sun Mar 29 09:21:15 2015 -0400 @@ -4362,13 +4362,14 @@ + # This line needs to be here, verbatim, after all includes and the dummy hook # definitions. It is replaced with custom functionality when building # custom sources. #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1425994551 +DATE_WHEN_GENERATED=1426774983 ############################################################################### # @@ -41173,7 +41174,7 @@ # jtreg win32 script works for everybody - JTREGEXE="$JT_HOME/win32/bin/jtreg" + JTREGEXE="$JT_HOME/bin/jtreg" if test ! -f "$JTREGEXE"; then as_fn_error $? "JTReg executable does not exist: $JTREGEXE" "$LINENO" 5 @@ -42372,9 +42373,8 @@ CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" fi if test "x$CFLAGS" != "x${ADDED_CFLAGS}"; then @@ -42668,6 +42668,8 @@ elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -liconv -bexpall -bernotok" fi # Customize LDFLAGS for executables @@ -52969,6 +52971,7 @@ fi + # Try to move the config.log file to the output directory. if test -e ./config.log; then $MV -f ./config.log "$OUTPUT_ROOT/config.log" 2> /dev/null diff -r f07d88b6243c -r cdecfa325d0c common/autoconf/toolchain.m4 --- a/common/autoconf/toolchain.m4 Wed Mar 25 15:22:45 2015 +0000 +++ b/common/autoconf/toolchain.m4 Sun Mar 29 09:21:15 2015 -0400 @@ -763,7 +763,7 @@ BASIC_FIXUP_PATH([JT_HOME]) # jtreg win32 script works for everybody - JTREGEXE="$JT_HOME/win32/bin/jtreg" + JTREGEXE="$JT_HOME/bin/jtreg" if test ! -f "$JTREGEXE"; then AC_MSG_ERROR([JTReg executable does not exist: $JTREGEXE]) diff -r f07d88b6243c -r cdecfa325d0c corba/.hgtags --- a/corba/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/corba/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -297,3 +297,4 @@ b8538bbb6f224ab1dabba579137099c166ad4724 jdk9-b52 aadc16ca5ab7d56f92ef9dbfa443595a939241b4 jdk9-b53 d469c5ad0c763e325a78e0af3016878a57dfc5cc jdk9-b54 +734ca5311a225711b79618f3e92f47f07c82154a jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c hotspot/.hgtags --- a/hotspot/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -457,3 +457,4 @@ 9fb7fdc554db5be5c5b10f88f529ec3b870c44e3 jdk9-b52 effd5ef0c3eb4bb85aa975c489d6761dbf13ad6a jdk9-b53 c3b117fa5bdedfafd9ed236403e6d406911195b1 jdk9-b54 +be49ab55e5c498c5077bbf58c2737100d1992339 jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c hotspot/agent/src/os/linux/libproc.h --- a/hotspot/agent/src/os/linux/libproc.h Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/agent/src/os/linux/libproc.h Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include #include "proc_service.h" -#if defined(arm) || defined(ppc) +#ifdef ALT_SASRCDIR #include "libproc_md.h" #endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Sun Mar 29 09:21:15 2015 -0400 @@ -51,6 +51,9 @@ private static final int C_INT32_SIZE = 4; private static final int C_INT64_SIZE = 8; private static int pointerSize = UNINITIALIZED_SIZE; + // Counter to ensure read loops terminate: + private static final int MAX_DUPLICATE_DEFINITIONS = 100; + private int duplicateDefCount = 0; private static final boolean DEBUG; static { @@ -166,6 +169,10 @@ typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); + if (typeEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Start iterating down it until we find an entry with no name Address typeNameAddr = null; do { @@ -192,7 +199,11 @@ } entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); - } while (typeNameAddr != null); + } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions"); + } } private void initializePrimitiveTypes() { @@ -395,6 +406,10 @@ structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); + if (structEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Fetch the address of the VMStructEntry* Address entryAddr = lookupInProcess("gHotSpotVMStructs"); // Dereference this once to get the pointer to the first VMStructEntry @@ -472,6 +487,11 @@ intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); + if (intConstantEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + + // Fetch the address of the VMIntConstantEntry* Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); // Dereference this once to get the pointer to the first VMIntConstantEntry @@ -501,12 +521,17 @@ } else { System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + "had its value declared as " + value + " twice. Continuing."); + duplicateDefCount++; } } } entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); - } while (nameAddr != null); + } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions"); + } } private void readVMLongConstants() { @@ -519,6 +544,10 @@ longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); + if (longConstantEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Fetch the address of the VMLongConstantEntry* Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); // Dereference this once to get the pointer to the first VMLongConstantEntry @@ -548,12 +577,17 @@ } else { System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + "had its value declared as " + value + " twice. Continuing."); + duplicateDefCount++; } } } entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); - } while (nameAddr != null); + } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions."); + } } private BasicType lookupOrFail(String typeName) { @@ -740,9 +774,10 @@ } if (!typeNameIsPointerType(typeName)) { - System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + - "had its size declared as " + size + " twice. Continuing."); - } + System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + + "had its size declared as " + size + " twice. Continuing."); + duplicateDefCount++; + } } } diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/aix/makefiles/rules.make --- a/hotspot/make/aix/makefiles/rules.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/aix/makefiles/rules.make Sun Mar 29 09:21:15 2015 -0400 @@ -126,10 +126,17 @@ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/bsd/makefiles/rules.make --- a/hotspot/make/bsd/makefiles/rules.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/bsd/makefiles/rules.make Sun Mar 29 09:21:15 2015 -0400 @@ -126,10 +126,17 @@ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/defs.make --- a/hotspot/make/defs.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/defs.make Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -286,7 +286,7 @@ # Use uname output for SRCARCH, but deal with platform differences. If ARCH # is not explicitly listed below, it is treated as x86. - SRCARCH = $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 arm ppc ppc64 aarch64 zero,$(ARCH))) + SRCARCH ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc ppc64 aarch64 zero,$(ARCH))) ARCH/ = x86 ARCH/sparc = sparc ARCH/sparc64= sparc @@ -295,12 +295,11 @@ ARCH/x86_64 = x86 ARCH/ppc64 = ppc ARCH/ppc = ppc - ARCH/arm = arm ARCH/aarch64= aarch64 ARCH/zero = zero # BUILDARCH is usually the same as SRCARCH, except for sparcv9 - BUILDARCH = $(SRCARCH) + BUILDARCH ?= $(SRCARCH) ifeq ($(BUILDARCH), x86) ifdef LP64 BUILDARCH = amd64 @@ -320,7 +319,7 @@ endif # LIBARCH is 1:1 mapping from BUILDARCH - LIBARCH = $(LIBARCH/$(BUILDARCH)) + LIBARCH ?= $(LIBARCH/$(BUILDARCH)) LIBARCH/i486 = i386 LIBARCH/amd64 = amd64 LIBARCH/sparc = sparc @@ -328,8 +327,6 @@ LIBARCH/ia64 = ia64 LIBARCH/ppc64 = ppc64 LIBARCH/aarch64 = aarch64 - LIBARCH/ppc = ppc - LIBARCH/arm = arm LIBARCH/zero = $(ZERO_LIBARCH) LP64_ARCH = sparcv9 amd64 ia64 ppc64 aarch64 zero @@ -347,6 +344,8 @@ # includes this make/defs.make file. MAKE_ARGS += HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) +MAKE_ARGS += BOOT_JDK_SOURCETARGET="$(BOOT_JDK_SOURCETARGET)" + # Various export sub directories EXPORT_INCLUDE_DIR = $(EXPORT_PATH)/include EXPORT_DOCS_DIR = $(EXPORT_PATH)/docs diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/arm.make --- a/hotspot/make/linux/makefiles/arm.make Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -# -# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -Obj_Files += linux_arm.o - -ifneq ($(EXT_LIBS_PATH),) - LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a -endif - -CFLAGS += -DVM_LITTLE_ENDIAN diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/buildtree.make --- a/hotspot/make/linux/makefiles/buildtree.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/linux/makefiles/buildtree.make Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -70,6 +70,8 @@ PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc else PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) + ALT_PLATFORM_FILE = $(HS_ALT_MAKE)/$(OS_FAMILY)/platform_$(BUILDARCH) + PLATFORM_FILE := $(if $(wildcard $(ALT_PLATFORM_FILE)),$(ALT_PLATFORM_FILE),$(PLATFORM_FILE)) endif endif @@ -203,7 +205,7 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo; \ - echo "Platform_file = $(PLATFORM_FILE)" | sed 's|$(GAMMADIR)|$$(GAMMADIR)|'; \ + echo "Platform_file = $(PLATFORM_FILE)" | sed -e 's|$(HS_ALT_MAKE)|$$(HS_ALT_MAKE)|' -e 's|$(GAMMADIR)|$$(GAMMADIR)|'; \ sed -n '/=/s/^ */Platform_/p' < $(PLATFORM_FILE); \ echo; \ echo "GAMMADIR = $(GAMMADIR)"; \ diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/defs.make --- a/hotspot/make/linux/makefiles/defs.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/linux/makefiles/defs.make Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -105,14 +105,6 @@ HS_ARCH = x86 endif -# ARM -ifeq ($(ARCH), arm) - ARCH_DATA_MODEL = 32 - PLATFORM = linux-arm - VM_PLATFORM = linux_arm - HS_ARCH = arm -endif - # PPC # Notice: after 8046471 ARCH will be 'ppc' for top-level ppc64 builds but # 'ppc64' for HotSpot-only ppc64 builds. Need to detect both variants here! @@ -121,10 +113,6 @@ MAKE_ARGS += LP64=1 PLATFORM = linux-ppc64 VM_PLATFORM = linux_ppc64 - else - ARCH_DATA_MODEL = 32 - PLATFORM = linux-ppc - VM_PLATFORM = linux_ppc endif HS_ARCH = ppc diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/gcc.make --- a/hotspot/make/linux/makefiles/gcc.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/linux/makefiles/gcc.make Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -176,11 +176,7 @@ ARCHFLAG/ia64 = ARCHFLAG/sparc = -m32 -mcpu=v9 ARCHFLAG/sparcv9 = -m64 -mcpu=v9 -ARCHFLAG/arm = -fsigned-char ARCHFLAG/zero = $(ZERO_ARCHFLAG) -ifndef E500V2 -ARCHFLAG/ppc = -mcpu=powerpc -endif ARCHFLAG/ppc64 = -m64 CFLAGS += $(ARCHFLAG) @@ -188,10 +184,6 @@ LFLAGS += $(ARCHFLAG) ASFLAGS += $(ARCHFLAG) -ifdef E500V2 -CFLAGS += -DE500V2 -endif - # Use C++ Interpreter ifdef CC_INTERP CFLAGS += -DCC_INTERP @@ -391,3 +383,5 @@ ifndef USE_SUNCC CFLAGS += -fno-omit-frame-pointer endif + +-include $(HS_ALT_MAKE)/linux/makefiles/gcc.make diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/ppc.make --- a/hotspot/make/linux/makefiles/ppc.make Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -# -# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized -OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) - -# Must also specify if CPU is big endian -CFLAGS += -DVM_BIG_ENDIAN - -ifdef E500V2 -ASFLAGS += -Wa,-mspe -Wa,--defsym -Wa,E500V2=1 -endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/rules.make --- a/hotspot/make/linux/makefiles/rules.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/linux/makefiles/rules.make Sun Mar 29 09:21:15 2015 -0400 @@ -126,10 +126,17 @@ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/saproc.make --- a/hotspot/make/linux/makefiles/saproc.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/linux/makefiles/saproc.make Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -69,19 +69,21 @@ endif ifneq ($(ALT_SASRCDIR),) -ALT_SAINCDIR=-I$(ALT_SASRCDIR) +ALT_SAINCDIR=-I$(ALT_SASRCDIR) -DALT_SASRCDIR else ALT_SAINCDIR= endif SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE)) $(LDFLAGS_HASH_STYLE) +SAARCH ?= $(BUILDARCH) + $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ exit 1; \ fi @echo $(LOG_INFO) Making SA debugger back-end... - $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \ + $(QUIETLY) $(CC) -D$(SAARCH) -D_GNU_SOURCE \ -D_FILE_OFFSET_BITS=64 \ $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ -I$(SASRCDIR) \ diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/makefiles/vm.make --- a/hotspot/make/linux/makefiles/vm.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/linux/makefiles/vm.make Sun Mar 29 09:21:15 2015 -0400 @@ -45,8 +45,9 @@ ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) include $(MAKEFILES_DIR)/zeroshark.make else - include $(MAKEFILES_DIR)/$(BUILDARCH).make - -include $(HS_ALT_MAKE)/$(Platform_os_family)/makefiles/$(BUILDARCH).make + BUILDARCH_MAKE = $(MAKEFILES_DIR)/$(BUILDARCH).make + ALT_BUILDARCH_MAKE = $(HS_ALT_MAKE)/$(Platform_os_family)/makefiles/$(BUILDARCH).make + include $(if $(wildcard $(ALT_BUILDARCH_MAKE)),$(ALT_BUILDARCH_MAKE),$(BUILDARCH_MAKE)) endif # set VPATH so make knows where to look for source files diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/platform_arm --- a/hotspot/make/linux/platform_arm Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -os_family = linux - -arch = arm - -arch_model = arm - -os_arch = linux_arm - -os_arch_model = linux_arm - -lib_arch = arm - -compiler = gcc - -gnu_dis_arch = arm - -sysdefs = -DLINUX -D_GNU_SOURCE -DARM diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/linux/platform_ppc --- a/hotspot/make/linux/platform_ppc Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -os_family = linux - -arch = ppc - -arch_model = ppc_32 - -os_arch = linux_ppc - -os_arch_model = linux_ppc_32 - -lib_arch = ppc - -compiler = gcc - -gnu_dis_arch = ppc - -sysdefs = -DLINUX -D_GNU_SOURCE -DPPC32 diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/solaris/makefiles/rules.make --- a/hotspot/make/solaris/makefiles/rules.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/solaris/makefiles/rules.make Sun Mar 29 09:21:15 2015 -0400 @@ -118,10 +118,17 @@ RUN.JAR$(MAKE_VERBOSE) += >/dev/null # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION = 6 -BOOT_TARGET_CLASS_VERSION = 6 JAVAC_FLAGS = -g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +ifeq ($(BOOT_JDK_SOURCETARGET),) +BOOTSTRAP_SOURCETARGET := -source 8 -target 8 +else +BOOTSTRAP_SOURCETARGET := $(BOOT_JDK_SOURCETARGET) +endif + +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # With parallel makes, print a message at the end of compilation. ifeq ($(findstring j,$(MFLAGS)),j) diff -r f07d88b6243c -r cdecfa325d0c hotspot/make/windows/makefiles/rules.make --- a/hotspot/make/windows/makefiles/rules.make Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/make/windows/makefiles/rules.make Sun Mar 29 09:21:15 2015 -0400 @@ -44,10 +44,17 @@ !endif # Settings for javac -BOOT_SOURCE_LANGUAGE_VERSION=6 -BOOT_TARGET_CLASS_VERSION=6 JAVAC_FLAGS=-g -encoding ascii -BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# Prefer BOOT_JDK_SOURCETARGET if it's set (typically by the top build system) +# Fall back to the values here if it's not set (hotspot only builds) +!ifndef BOOT_JDK_SOURCETARGET +BOOTSTRAP_SOURCETARGET=-source 8 -target 8 +!else +BOOTSTRAP_SOURCETARGET=$(BOOT_JDK_SOURCETARGET) +!endif + +BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) $(BOOTSTRAP_SOURCETARGET) # VS2012 and VS2013 loads VS10 projects just fine (and will # upgrade them automatically to VS2012 format). diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -2776,7 +2776,6 @@ __ stop("unexpected profiling mismatch"); __ bind(ok); - __ pop(tmp); } #endif // first time here. Set profile type. diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -872,7 +872,7 @@ // stack grows down, caller passes positive offset assert(offset > 0, "must bang with negative offset"); mov(rscratch2, -offset); - ldr(zr, Address(sp, rscratch2)); + str(zr, Address(sp, rscratch2)); } // Writes to stack successive pages until offset reached to check for diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -858,7 +858,7 @@ const int page_size = os::vm_page_size(); for (int pages = start_page; pages <= StackShadowPages ; pages++) { __ sub(rscratch2, sp, pages*page_size); - __ ldr(zr, Address(rscratch2)); + __ str(zr, Address(rscratch2)); } } } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -3947,12 +3947,10 @@ void LIR_Assembler::membar_acquire() { // No x86 machines currently require load fences - // __ load_fence(); } void LIR_Assembler::membar_release() { // No x86 machines currently require store fences - // __ store_fence(); } void LIR_Assembler::membar_loadload() { diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/x86/vm/templateTable_x86.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,4235 @@ +/* + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "asm/macroAssembler.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "interpreter/interp_masm.hpp" +#include "interpreter/templateTable.hpp" +#include "memory/universe.inline.hpp" +#include "oops/methodData.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" + +#ifndef CC_INTERP + +#define __ _masm-> + +// Global Register Names +Register rbcp = LP64_ONLY(r13) NOT_LP64(rsi); +Register rlocals = LP64_ONLY(r14) NOT_LP64(rdi); + +// Platform-dependent initialization +void TemplateTable::pd_initialize() { + // No x86 specific initialization +} + +// Address Computation: local variables +static inline Address iaddress(int n) { + return Address(rlocals, Interpreter::local_offset_in_bytes(n)); +} + +static inline Address laddress(int n) { + return iaddress(n + 1); +} + +#ifndef _LP64 +static inline Address haddress(int n) { + return iaddress(n + 0); +} +#endif + +static inline Address faddress(int n) { + return iaddress(n); +} + +static inline Address daddress(int n) { + return laddress(n); +} + +static inline Address aaddress(int n) { + return iaddress(n); +} + +static inline Address iaddress(Register r) { + return Address(rlocals, r, Address::times_ptr); +} + +static inline Address laddress(Register r) { + return Address(rlocals, r, Address::times_ptr, Interpreter::local_offset_in_bytes(1)); +} + +#ifndef _LP64 +static inline Address haddress(Register r) { + return Address(rlocals, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(0)); +} +#endif + +static inline Address faddress(Register r) { + return iaddress(r); +} + +static inline Address daddress(Register r) { + return laddress(r); +} + +static inline Address aaddress(Register r) { + return iaddress(r); +} + + +// expression stack +// (Note: Must not use symmetric equivalents at_rsp_m1/2 since they store +// data beyond the rsp which is potentially unsafe in an MT environment; +// an interrupt may overwrite that data.) +static inline Address at_rsp () { + return Address(rsp, 0); +} + +// At top of Java expression stack which may be different than esp(). It +// isn't for category 1 objects. +static inline Address at_tos () { + return Address(rsp, Interpreter::expr_offset_in_bytes(0)); +} + +static inline Address at_tos_p1() { + return Address(rsp, Interpreter::expr_offset_in_bytes(1)); +} + +static inline Address at_tos_p2() { + return Address(rsp, Interpreter::expr_offset_in_bytes(2)); +} + +// Condition conversion +static Assembler::Condition j_not(TemplateTable::Condition cc) { + switch (cc) { + case TemplateTable::equal : return Assembler::notEqual; + case TemplateTable::not_equal : return Assembler::equal; + case TemplateTable::less : return Assembler::greaterEqual; + case TemplateTable::less_equal : return Assembler::greater; + case TemplateTable::greater : return Assembler::lessEqual; + case TemplateTable::greater_equal: return Assembler::less; + } + ShouldNotReachHere(); + return Assembler::zero; +} + + + +// Miscelaneous helper routines +// Store an oop (or NULL) at the address described by obj. +// If val == noreg this means store a NULL + + +static void do_oop_store(InterpreterMacroAssembler* _masm, + Address obj, + Register val, + BarrierSet::Name barrier, + bool precise) { + assert(val == noreg || val == rax, "parameter is just for looks"); + switch (barrier) { +#if INCLUDE_ALL_GCS + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: + { + // flatten object address if needed + // We do it regardless of precise because we need the registers + if (obj.index() == noreg && obj.disp() == 0) { + if (obj.base() != rdx) { + __ movptr(rdx, obj.base()); + } + } else { + __ lea(rdx, obj); + } + + Register rtmp = LP64_ONLY(r8) NOT_LP64(rsi); + Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + + NOT_LP64(__ get_thread(rcx)); + NOT_LP64(__ save_bcp()); + + __ g1_write_barrier_pre(rdx /* obj */, + rbx /* pre_val */, + rthread /* thread */, + rtmp /* tmp */, + val != noreg /* tosca_live */, + false /* expand_call */); + if (val == noreg) { + __ store_heap_oop_null(Address(rdx, 0)); + } else { + // G1 barrier needs uncompressed oop for region cross check. + Register new_val = val; + if (UseCompressedOops) { + new_val = rbx; + __ movptr(new_val, val); + } + __ store_heap_oop(Address(rdx, 0), val); + __ g1_write_barrier_post(rdx /* store_adr */, + new_val /* new_val */, + rthread /* thread */, + rtmp /* tmp */, + rbx /* tmp2 */); + } + NOT_LP64( __ restore_bcp()); + } + break; +#endif // INCLUDE_ALL_GCS + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + { + if (val == noreg) { + __ store_heap_oop_null(obj); + } else { + __ store_heap_oop(obj, val); + // flatten object address if needed + if (!precise || (obj.index() == noreg && obj.disp() == 0)) { + __ store_check(obj.base()); + } else { + __ lea(rdx, obj); + __ store_check(rdx); + } + } + } + break; + case BarrierSet::ModRef: + if (val == noreg) { + __ store_heap_oop_null(obj); + } else { + __ store_heap_oop(obj, val); + } + break; + default : + ShouldNotReachHere(); + + } +} + +Address TemplateTable::at_bcp(int offset) { + assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); + return Address(rbcp, offset); +} + + +void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, + Register temp_reg, bool load_bc_into_bc_reg/*=true*/, + int byte_no) { + if (!RewriteBytecodes) return; + Label L_patch_done; + + switch (bc) { + case Bytecodes::_fast_aputfield: + case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_cputfield: + case Bytecodes::_fast_dputfield: + case Bytecodes::_fast_fputfield: + case Bytecodes::_fast_iputfield: + case Bytecodes::_fast_lputfield: + case Bytecodes::_fast_sputfield: + { + // We skip bytecode quickening for putfield instructions when + // the put_code written to the constant pool cache is zero. + // This is required so that every execution of this instruction + // calls out to InterpreterRuntime::resolve_get_put to do + // additional, required work. + assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + assert(load_bc_into_bc_reg, "we use bc_reg as temp"); + __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1); + __ movl(bc_reg, bc); + __ cmpl(temp_reg, (int) 0); + __ jcc(Assembler::zero, L_patch_done); // don't patch + } + break; + default: + assert(byte_no == -1, "sanity"); + // the pair bytecodes have already done the load. + if (load_bc_into_bc_reg) { + __ movl(bc_reg, bc); + } + } + + if (JvmtiExport::can_post_breakpoint()) { + Label L_fast_patch; + // if a breakpoint is present we can't rewrite the stream directly + __ movzbl(temp_reg, at_bcp(0)); + __ cmpl(temp_reg, Bytecodes::_breakpoint); + __ jcc(Assembler::notEqual, L_fast_patch); + __ get_method(temp_reg); + // Let breakpoint table handling rewrite to quicker bytecode + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, rbcp, bc_reg); +#ifndef ASSERT + __ jmpb(L_patch_done); +#else + __ jmp(L_patch_done); +#endif + __ bind(L_fast_patch); + } + +#ifdef ASSERT + Label L_okay; + __ load_unsigned_byte(temp_reg, at_bcp(0)); + __ cmpl(temp_reg, (int) Bytecodes::java_code(bc)); + __ jcc(Assembler::equal, L_okay); + __ cmpl(temp_reg, bc_reg); + __ jcc(Assembler::equal, L_okay); + __ stop("patching the wrong bytecode"); + __ bind(L_okay); +#endif + + // patch bytecode + __ movb(at_bcp(0), bc_reg); + __ bind(L_patch_done); +} +// Individual instructions + + +void TemplateTable::nop() { + transition(vtos, vtos); + // nothing to do +} + +void TemplateTable::shouldnotreachhere() { + transition(vtos, vtos); + __ stop("shouldnotreachhere bytecode"); +} + +void TemplateTable::aconst_null() { + transition(vtos, atos); + __ xorl(rax, rax); +} + +void TemplateTable::iconst(int value) { + transition(vtos, itos); + if (value == 0) { + __ xorl(rax, rax); + } else { + __ movl(rax, value); + } +} + +void TemplateTable::lconst(int value) { + transition(vtos, ltos); + if (value == 0) { + __ xorl(rax, rax); + } else { + __ movl(rax, value); + } +#ifndef _LP64 + assert(value >= 0, "check this code"); + __ xorptr(rdx, rdx); +#endif +} + + + +void TemplateTable::fconst(int value) { + transition(vtos, ftos); +#ifdef _LP64 + static float one = 1.0f, two = 2.0f; + switch (value) { + case 0: + __ xorps(xmm0, xmm0); + break; + case 1: + __ movflt(xmm0, ExternalAddress((address) &one)); + break; + case 2: + __ movflt(xmm0, ExternalAddress((address) &two)); + break; + default: + ShouldNotReachHere(); + break; + } +#else + if (value == 0) { __ fldz(); + } else if (value == 1) { __ fld1(); + } else if (value == 2) { __ fld1(); __ fld1(); __ faddp(); // should do a better solution here + } else { ShouldNotReachHere(); + } +#endif +} + +void TemplateTable::dconst(int value) { + transition(vtos, dtos); +#ifdef _LP64 + static double one = 1.0; + switch (value) { + case 0: + __ xorpd(xmm0, xmm0); + break; + case 1: + __ movdbl(xmm0, ExternalAddress((address) &one)); + break; + default: + ShouldNotReachHere(); + break; + } + +#else + if (value == 0) { __ fldz(); + } else if (value == 1) { __ fld1(); + } else { ShouldNotReachHere(); + } +#endif +} + +void TemplateTable::bipush() { + transition(vtos, itos); + __ load_signed_byte(rax, at_bcp(1)); +} + +void TemplateTable::sipush() { + transition(vtos, itos); + __ load_unsigned_short(rax, at_bcp(1)); + __ bswapl(rax); + __ sarl(rax, 16); +} + +void TemplateTable::ldc(bool wide) { + transition(vtos, vtos); + Register rarg = NOT_LP64(rcx) LP64_ONLY(c_rarg1); + Label call_ldc, notFloat, notClass, Done; + + if (wide) { + __ get_unsigned_2_byte_index_at_bcp(rbx, 1); + } else { + __ load_unsigned_byte(rbx, at_bcp(1)); + } + + __ get_cpool_and_tags(rcx, rax); + const int base_offset = ConstantPool::header_size() * wordSize; + const int tags_offset = Array::base_offset_in_bytes(); + + // get type + __ movzbl(rdx, Address(rax, rbx, Address::times_1, tags_offset)); + + // unresolved class - get the resolved class + __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass); + __ jccb(Assembler::equal, call_ldc); + + // unresolved class in error state - call into runtime to throw the error + // from the first resolution attempt + __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError); + __ jccb(Assembler::equal, call_ldc); + + // resolved class - need to call vm to get java mirror of the class + __ cmpl(rdx, JVM_CONSTANT_Class); + __ jcc(Assembler::notEqual, notClass); + + __ bind(call_ldc); + + __ movl(rarg, wide); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), rarg); + + __ push(atos); + __ jmp(Done); + + __ bind(notClass); + __ cmpl(rdx, JVM_CONSTANT_Float); + __ jccb(Assembler::notEqual, notFloat); + + // ftos + LP64_ONLY(__ movflt(xmm0, Address(rcx, rbx, Address::times_8, base_offset))); + NOT_LP64(__ fld_s( Address(rcx, rbx, Address::times_ptr, base_offset))); + __ push(ftos); + __ jmp(Done); + + __ bind(notFloat); +#ifdef ASSERT + { + Label L; + __ cmpl(rdx, JVM_CONSTANT_Integer); + __ jcc(Assembler::equal, L); + // String and Object are rewritten to fast_aldc + __ stop("unexpected tag type in ldc"); + __ bind(L); + } +#endif + // itos JVM_CONSTANT_Integer only + __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset)); + __ push(itos); + __ bind(Done); +} + +// Fast path for caching oop constants. +void TemplateTable::fast_aldc(bool wide) { + transition(vtos, atos); + + Register result = rax; + Register tmp = rdx; + int index_size = wide ? sizeof(u2) : sizeof(u1); + + Label resolved; + + // We are resolved if the resolved reference cache entry contains a + // non-null object (String, MethodType, etc.) + assert_different_registers(result, tmp); + __ get_cache_index_at_bcp(tmp, 1, index_size); + __ load_resolved_reference_at_index(result, tmp); + __ testl(result, result); + __ jcc(Assembler::notZero, resolved); + + address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); + + // first time invocation - must resolve first + __ movl(tmp, (int)bytecode()); + __ call_VM(result, entry, tmp); + + __ bind(resolved); + + if (VerifyOops) { + __ verify_oop(result); + } +} + +void TemplateTable::ldc2_w() { + transition(vtos, vtos); + Label Long, Done; + __ get_unsigned_2_byte_index_at_bcp(rbx, 1); + + __ get_cpool_and_tags(rcx, rax); + const int base_offset = ConstantPool::header_size() * wordSize; + const int tags_offset = Array::base_offset_in_bytes(); + + // get type + __ cmpb(Address(rax, rbx, Address::times_1, tags_offset), + JVM_CONSTANT_Double); + __ jccb(Assembler::notEqual, Long); + + // dtos + LP64_ONLY(__ movdbl(xmm0, Address(rcx, rbx, Address::times_8, base_offset))); + NOT_LP64(__ fld_d( Address(rcx, rbx, Address::times_ptr, base_offset))); + __ push(dtos); + + __ jmpb(Done); + __ bind(Long); + + // ltos + __ movptr(rax, Address(rcx, rbx, Address::times_ptr, base_offset + 0 * wordSize)); + NOT_LP64(__ movptr(rdx, Address(rcx, rbx, Address::times_ptr, base_offset + 1 * wordSize))); + __ push(ltos); + + __ bind(Done); +} + +void TemplateTable::locals_index(Register reg, int offset) { + __ load_unsigned_byte(reg, at_bcp(offset)); + __ negptr(reg); +} + +void TemplateTable::iload() { + transition(vtos, itos); + if (RewriteFrequentPairs) { + Label rewrite, done; + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + LP64_ONLY(assert(rbx != bc, "register damaged")); + + // get next byte + __ load_unsigned_byte(rbx, + at_bcp(Bytecodes::length_for(Bytecodes::_iload))); + // if _iload, wait to rewrite to iload2. We only want to rewrite the + // last two iloads in a pair. Comparing against fast_iload means that + // the next bytecode is neither an iload or a caload, and therefore + // an iload pair. + __ cmpl(rbx, Bytecodes::_iload); + __ jcc(Assembler::equal, done); + + __ cmpl(rbx, Bytecodes::_fast_iload); + __ movl(bc, Bytecodes::_fast_iload2); + + __ jccb(Assembler::equal, rewrite); + + // if _caload, rewrite to fast_icaload + __ cmpl(rbx, Bytecodes::_caload); + __ movl(bc, Bytecodes::_fast_icaload); + __ jccb(Assembler::equal, rewrite); + + // rewrite so iload doesn't check again. + __ movl(bc, Bytecodes::_fast_iload); + + // rewrite + // bc: fast bytecode + __ bind(rewrite); + patch_bytecode(Bytecodes::_iload, bc, rbx, false); + __ bind(done); + } + + // Get the local value into tos + locals_index(rbx); + __ movl(rax, iaddress(rbx)); +} + +void TemplateTable::fast_iload2() { + transition(vtos, itos); + locals_index(rbx); + __ movl(rax, iaddress(rbx)); + __ push(itos); + locals_index(rbx, 3); + __ movl(rax, iaddress(rbx)); +} + +void TemplateTable::fast_iload() { + transition(vtos, itos); + locals_index(rbx); + __ movl(rax, iaddress(rbx)); +} + +void TemplateTable::lload() { + transition(vtos, ltos); + locals_index(rbx); + __ movptr(rax, laddress(rbx)); + NOT_LP64(__ movl(rdx, haddress(rbx))); +} + +void TemplateTable::fload() { + transition(vtos, ftos); + locals_index(rbx); + LP64_ONLY(__ movflt(xmm0, faddress(rbx))); + NOT_LP64(__ fld_s(faddress(rbx))); +} + +void TemplateTable::dload() { + transition(vtos, dtos); + locals_index(rbx); + LP64_ONLY(__ movdbl(xmm0, daddress(rbx))); + NOT_LP64(__ fld_d(daddress(rbx))); +} + +void TemplateTable::aload() { + transition(vtos, atos); + locals_index(rbx); + __ movptr(rax, aaddress(rbx)); +} + +void TemplateTable::locals_index_wide(Register reg) { + __ load_unsigned_short(reg, at_bcp(2)); + __ bswapl(reg); + __ shrl(reg, 16); + __ negptr(reg); +} + +void TemplateTable::wide_iload() { + transition(vtos, itos); + locals_index_wide(rbx); + __ movl(rax, iaddress(rbx)); +} + +void TemplateTable::wide_lload() { + transition(vtos, ltos); + locals_index_wide(rbx); + __ movptr(rax, laddress(rbx)); + NOT_LP64(__ movl(rdx, haddress(rbx))); +} + +void TemplateTable::wide_fload() { + transition(vtos, ftos); + locals_index_wide(rbx); + LP64_ONLY(__ movflt(xmm0, faddress(rbx))); + NOT_LP64(__ fld_s(faddress(rbx))); +} + +void TemplateTable::wide_dload() { + transition(vtos, dtos); + locals_index_wide(rbx); + LP64_ONLY(__ movdbl(xmm0, daddress(rbx))); + NOT_LP64(__ fld_d(daddress(rbx))); +} + +void TemplateTable::wide_aload() { + transition(vtos, atos); + locals_index_wide(rbx); + __ movptr(rax, aaddress(rbx)); +} + +void TemplateTable::index_check(Register array, Register index) { + // Pop ptr into array + __ pop_ptr(array); + index_check_without_pop(array, index); +} + +void TemplateTable::index_check_without_pop(Register array, Register index) { + // destroys rbx + // check array + __ null_check(array, arrayOopDesc::length_offset_in_bytes()); + // sign extend index for use by indexed load + __ movl2ptr(index, index); + // check index + __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes())); + if (index != rbx) { + // ??? convention: move aberrant index into rbx for exception message + assert(rbx != array, "different registers"); + __ movl(rbx, index); + } + __ jump_cc(Assembler::aboveEqual, + ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); +} + + +void TemplateTable::iaload() { + transition(itos, itos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + __ movl(rax, Address(rdx, rax, + Address::times_4, + arrayOopDesc::base_offset_in_bytes(T_INT))); +} + +void TemplateTable::laload() { + transition(itos, ltos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + NOT_LP64(__ mov(rbx, rax)); + // rbx,: index + __ movptr(rax, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize)); + NOT_LP64(__ movl(rdx, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize))); +} + + + +void TemplateTable::faload() { + transition(itos, ftos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + LP64_ONLY(__ movflt(xmm0, Address(rdx, rax, + Address::times_4, + arrayOopDesc::base_offset_in_bytes(T_FLOAT)))); + NOT_LP64(__ fld_s(Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)))); +} + +void TemplateTable::daload() { + transition(itos, dtos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + LP64_ONLY(__ movdbl(xmm0, Address(rdx, rax, + Address::times_8, + arrayOopDesc::base_offset_in_bytes(T_DOUBLE)))); + NOT_LP64(__ fld_d(Address(rdx, rax, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)))); +} + +void TemplateTable::aaload() { + transition(itos, atos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + __ load_heap_oop(rax, Address(rdx, rax, + UseCompressedOops ? Address::times_4 : Address::times_ptr, + arrayOopDesc::base_offset_in_bytes(T_OBJECT))); +} + +void TemplateTable::baload() { + transition(itos, itos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + __ load_signed_byte(rax, Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE))); +} + +void TemplateTable::caload() { + transition(itos, itos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + __ load_unsigned_short(rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); +} + +// iload followed by caload frequent pair +void TemplateTable::fast_icaload() { + transition(vtos, itos); + // load index out of locals + locals_index(rbx); + __ movl(rax, iaddress(rbx)); + + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + __ load_unsigned_short(rax, + Address(rdx, rax, + Address::times_2, + arrayOopDesc::base_offset_in_bytes(T_CHAR))); +} + + +void TemplateTable::saload() { + transition(itos, itos); + // rax: index + // rdx: array + index_check(rdx, rax); // kills rbx + __ load_signed_short(rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); +} + +void TemplateTable::iload(int n) { + transition(vtos, itos); + __ movl(rax, iaddress(n)); +} + +void TemplateTable::lload(int n) { + transition(vtos, ltos); + __ movptr(rax, laddress(n)); + NOT_LP64(__ movptr(rdx, haddress(n))); +} + +void TemplateTable::fload(int n) { + transition(vtos, ftos); + LP64_ONLY(__ movflt(xmm0, faddress(n))); + NOT_LP64(__ fld_s(faddress(n))); +} + +void TemplateTable::dload(int n) { + transition(vtos, dtos); + LP64_ONLY(__ movdbl(xmm0, daddress(n))); + NOT_LP64(__ fld_d(daddress(n))); +} + +void TemplateTable::aload(int n) { + transition(vtos, atos); + __ movptr(rax, aaddress(n)); +} + +void TemplateTable::aload_0() { + transition(vtos, atos); + // According to bytecode histograms, the pairs: + // + // _aload_0, _fast_igetfield + // _aload_0, _fast_agetfield + // _aload_0, _fast_fgetfield + // + // occur frequently. If RewriteFrequentPairs is set, the (slow) + // _aload_0 bytecode checks if the next bytecode is either + // _fast_igetfield, _fast_agetfield or _fast_fgetfield and then + // rewrites the current bytecode into a pair bytecode; otherwise it + // rewrites the current bytecode into _fast_aload_0 that doesn't do + // the pair check anymore. + // + // Note: If the next bytecode is _getfield, the rewrite must be + // delayed, otherwise we may miss an opportunity for a pair. + // + // Also rewrite frequent pairs + // aload_0, aload_1 + // aload_0, iload_1 + // These bytecodes with a small amount of code are most profitable + // to rewrite + if (RewriteFrequentPairs) { + Label rewrite, done; + + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + LP64_ONLY(assert(rbx != bc, "register damaged")); + + // get next byte + __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); + + // do actual aload_0 + aload(0); + + // if _getfield then wait with rewrite + __ cmpl(rbx, Bytecodes::_getfield); + __ jcc(Assembler::equal, done); + + // if _igetfield then reqrite to _fast_iaccess_0 + assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ cmpl(rbx, Bytecodes::_fast_igetfield); + __ movl(bc, Bytecodes::_fast_iaccess_0); + __ jccb(Assembler::equal, rewrite); + + // if _agetfield then reqrite to _fast_aaccess_0 + assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ cmpl(rbx, Bytecodes::_fast_agetfield); + __ movl(bc, Bytecodes::_fast_aaccess_0); + __ jccb(Assembler::equal, rewrite); + + // if _fgetfield then reqrite to _fast_faccess_0 + assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ cmpl(rbx, Bytecodes::_fast_fgetfield); + __ movl(bc, Bytecodes::_fast_faccess_0); + __ jccb(Assembler::equal, rewrite); + + // else rewrite to _fast_aload0 + assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "fix bytecode definition"); + __ movl(bc, Bytecodes::_fast_aload_0); + + // rewrite + // bc: fast bytecode + __ bind(rewrite); + patch_bytecode(Bytecodes::_aload_0, bc, rbx, false); + + __ bind(done); + } else { + aload(0); + } +} + +void TemplateTable::istore() { + transition(itos, vtos); + locals_index(rbx); + __ movl(iaddress(rbx), rax); +} + + +void TemplateTable::lstore() { + transition(ltos, vtos); + locals_index(rbx); + __ movptr(laddress(rbx), rax); + NOT_LP64(__ movptr(haddress(rbx), rdx)); +} + +void TemplateTable::fstore() { + transition(ftos, vtos); + locals_index(rbx); + LP64_ONLY(__ movflt(faddress(rbx), xmm0)); + NOT_LP64(__ fstp_s(faddress(rbx))); +} + +void TemplateTable::dstore() { + transition(dtos, vtos); + locals_index(rbx); + LP64_ONLY(__ movdbl(daddress(rbx), xmm0)); + NOT_LP64(__ fstp_d(daddress(rbx))); +} + +void TemplateTable::astore() { + transition(vtos, vtos); + __ pop_ptr(rax); + locals_index(rbx); + __ movptr(aaddress(rbx), rax); +} + +void TemplateTable::wide_istore() { + transition(vtos, vtos); + __ pop_i(); + locals_index_wide(rbx); + __ movl(iaddress(rbx), rax); +} + +void TemplateTable::wide_lstore() { + transition(vtos, vtos); + NOT_LP64(__ pop_l(rax, rdx)); + LP64_ONLY(__ pop_l()); + locals_index_wide(rbx); + __ movptr(laddress(rbx), rax); + NOT_LP64(__ movl(haddress(rbx), rdx)); +} + +void TemplateTable::wide_fstore() { +#ifdef _LP64 + transition(vtos, vtos); + __ pop_f(); + locals_index_wide(rbx); + __ movflt(faddress(rbx), xmm0); +#else + wide_istore(); +#endif +} + +void TemplateTable::wide_dstore() { +#ifdef _LP64 + transition(vtos, vtos); + __ pop_d(); + locals_index_wide(rbx); + __ movdbl(daddress(rbx), xmm0); +#else + wide_lstore(); +#endif +} + +void TemplateTable::wide_astore() { + transition(vtos, vtos); + __ pop_ptr(rax); + locals_index_wide(rbx); + __ movptr(aaddress(rbx), rax); +} + +void TemplateTable::iastore() { + transition(itos, vtos); + __ pop_i(rbx); + // rax: value + // rbx: index + // rdx: array + index_check(rdx, rbx); // prefer index in rbx + __ movl(Address(rdx, rbx, + Address::times_4, + arrayOopDesc::base_offset_in_bytes(T_INT)), + rax); +} + +void TemplateTable::lastore() { + transition(ltos, vtos); + __ pop_i(rbx); + // rax,: low(value) + // rcx: array + // rdx: high(value) + index_check(rcx, rbx); // prefer index in rbx, + // rbx,: index + __ movptr(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize), rax); + NOT_LP64(__ movl(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize), rdx)); +} + + +void TemplateTable::fastore() { + transition(ftos, vtos); + __ pop_i(rbx); + // xmm0: value + // rbx: index + // rdx: array + index_check(rdx, rbx); // prefer index in rbx + LP64_ONLY(__ movflt(Address(rdx, rbx, + Address::times_4, + arrayOopDesc::base_offset_in_bytes(T_FLOAT)), + xmm0)); + NOT_LP64(__ fstp_s(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)))); +} + +void TemplateTable::dastore() { + transition(dtos, vtos); + __ pop_i(rbx); + // xmm0: value + // rbx: index + // rdx: array + index_check(rdx, rbx); // prefer index in rbx + LP64_ONLY(__ movdbl(Address(rdx, rbx, + Address::times_8, + arrayOopDesc::base_offset_in_bytes(T_DOUBLE)), + xmm0)); + NOT_LP64(__ fstp_d(Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)))); +} + +void TemplateTable::aastore() { + Label is_null, ok_is_subtype, done; + transition(vtos, vtos); + // stack: ..., array, index, value + __ movptr(rax, at_tos()); // value + __ movl(rcx, at_tos_p1()); // index + __ movptr(rdx, at_tos_p2()); // array + + Address element_address(rdx, rcx, + UseCompressedOops? Address::times_4 : Address::times_ptr, + arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + + index_check_without_pop(rdx, rcx); // kills rbx + __ testptr(rax, rax); + __ jcc(Assembler::zero, is_null); + + // Move subklass into rbx + __ load_klass(rbx, rax); + // Move superklass into rax + __ load_klass(rax, rdx); + __ movptr(rax, Address(rax, + ObjArrayKlass::element_klass_offset())); + // Compress array + index*oopSize + 12 into a single register. Frees rcx. + __ lea(rdx, element_address); + + // Generate subtype check. Blows rcx, rdi + // Superklass in rax. Subklass in rbx. + __ gen_subtype_check(rbx, ok_is_subtype); + + // Come here on failure + // object is at TOS + __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); + + // Come here on success + __ bind(ok_is_subtype); + + // Get the value we will store + __ movptr(rax, at_tos()); + // Now store using the appropriate barrier + do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true); + __ jmp(done); + + // Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx] + __ bind(is_null); + __ profile_null_seen(rbx); + + // Store a NULL + do_oop_store(_masm, element_address, noreg, _bs->kind(), true); + + // Pop stack arguments + __ bind(done); + __ addptr(rsp, 3 * Interpreter::stackElementSize); +} + +void TemplateTable::bastore() { + transition(itos, vtos); + __ pop_i(rbx); + // rax: value + // rbx: index + // rdx: array + index_check(rdx, rbx); // prefer index in rbx + __ movb(Address(rdx, rbx, + Address::times_1, + arrayOopDesc::base_offset_in_bytes(T_BYTE)), + rax); +} + +void TemplateTable::castore() { + transition(itos, vtos); + __ pop_i(rbx); + // rax: value + // rbx: index + // rdx: array + index_check(rdx, rbx); // prefer index in rbx + __ movw(Address(rdx, rbx, + Address::times_2, + arrayOopDesc::base_offset_in_bytes(T_CHAR)), + rax); +} + + +void TemplateTable::sastore() { + castore(); +} + +void TemplateTable::istore(int n) { + transition(itos, vtos); + __ movl(iaddress(n), rax); +} + +void TemplateTable::lstore(int n) { + transition(ltos, vtos); + __ movptr(laddress(n), rax); + NOT_LP64(__ movptr(haddress(n), rdx)); +} + +void TemplateTable::fstore(int n) { + transition(ftos, vtos); + LP64_ONLY(__ movflt(faddress(n), xmm0)); + NOT_LP64(__ fstp_s(faddress(n))); +} + +void TemplateTable::dstore(int n) { + transition(dtos, vtos); + LP64_ONLY(__ movdbl(daddress(n), xmm0)); + NOT_LP64(__ fstp_d(daddress(n))); +} + + +void TemplateTable::astore(int n) { + transition(vtos, vtos); + __ pop_ptr(rax); + __ movptr(aaddress(n), rax); +} + +void TemplateTable::pop() { + transition(vtos, vtos); + __ addptr(rsp, Interpreter::stackElementSize); +} + +void TemplateTable::pop2() { + transition(vtos, vtos); + __ addptr(rsp, 2 * Interpreter::stackElementSize); +} + + +void TemplateTable::dup() { + transition(vtos, vtos); + __ load_ptr(0, rax); + __ push_ptr(rax); + // stack: ..., a, a +} + +void TemplateTable::dup_x1() { + transition(vtos, vtos); + // stack: ..., a, b + __ load_ptr( 0, rax); // load b + __ load_ptr( 1, rcx); // load a + __ store_ptr(1, rax); // store b + __ store_ptr(0, rcx); // store a + __ push_ptr(rax); // push b + // stack: ..., b, a, b +} + +void TemplateTable::dup_x2() { + transition(vtos, vtos); + // stack: ..., a, b, c + __ load_ptr( 0, rax); // load c + __ load_ptr( 2, rcx); // load a + __ store_ptr(2, rax); // store c in a + __ push_ptr(rax); // push c + // stack: ..., c, b, c, c + __ load_ptr( 2, rax); // load b + __ store_ptr(2, rcx); // store a in b + // stack: ..., c, a, c, c + __ store_ptr(1, rax); // store b in c + // stack: ..., c, a, b, c +} + +void TemplateTable::dup2() { + transition(vtos, vtos); + // stack: ..., a, b + __ load_ptr(1, rax); // load a + __ push_ptr(rax); // push a + __ load_ptr(1, rax); // load b + __ push_ptr(rax); // push b + // stack: ..., a, b, a, b +} + + +void TemplateTable::dup2_x1() { + transition(vtos, vtos); + // stack: ..., a, b, c + __ load_ptr( 0, rcx); // load c + __ load_ptr( 1, rax); // load b + __ push_ptr(rax); // push b + __ push_ptr(rcx); // push c + // stack: ..., a, b, c, b, c + __ store_ptr(3, rcx); // store c in b + // stack: ..., a, c, c, b, c + __ load_ptr( 4, rcx); // load a + __ store_ptr(2, rcx); // store a in 2nd c + // stack: ..., a, c, a, b, c + __ store_ptr(4, rax); // store b in a + // stack: ..., b, c, a, b, c +} + +void TemplateTable::dup2_x2() { + transition(vtos, vtos); + // stack: ..., a, b, c, d + __ load_ptr( 0, rcx); // load d + __ load_ptr( 1, rax); // load c + __ push_ptr(rax); // push c + __ push_ptr(rcx); // push d + // stack: ..., a, b, c, d, c, d + __ load_ptr( 4, rax); // load b + __ store_ptr(2, rax); // store b in d + __ store_ptr(4, rcx); // store d in b + // stack: ..., a, d, c, b, c, d + __ load_ptr( 5, rcx); // load a + __ load_ptr( 3, rax); // load c + __ store_ptr(3, rcx); // store a in c + __ store_ptr(5, rax); // store c in a + // stack: ..., c, d, a, b, c, d +} + +void TemplateTable::swap() { + transition(vtos, vtos); + // stack: ..., a, b + __ load_ptr( 1, rcx); // load a + __ load_ptr( 0, rax); // load b + __ store_ptr(0, rcx); // store a in b + __ store_ptr(1, rax); // store b in a + // stack: ..., b, a +} + +void TemplateTable::iop2(Operation op) { + transition(itos, itos); + switch (op) { + case add : __ pop_i(rdx); __ addl (rax, rdx); break; + case sub : __ movl(rdx, rax); __ pop_i(rax); __ subl (rax, rdx); break; + case mul : __ pop_i(rdx); __ imull(rax, rdx); break; + case _and : __ pop_i(rdx); __ andl (rax, rdx); break; + case _or : __ pop_i(rdx); __ orl (rax, rdx); break; + case _xor : __ pop_i(rdx); __ xorl (rax, rdx); break; + case shl : __ movl(rcx, rax); __ pop_i(rax); __ shll (rax); break; + case shr : __ movl(rcx, rax); __ pop_i(rax); __ sarl (rax); break; + case ushr : __ movl(rcx, rax); __ pop_i(rax); __ shrl (rax); break; + default : ShouldNotReachHere(); + } +} + +void TemplateTable::lop2(Operation op) { + transition(ltos, ltos); +#ifdef _LP64 + switch (op) { + case add : __ pop_l(rdx); __ addptr(rax, rdx); break; + case sub : __ mov(rdx, rax); __ pop_l(rax); __ subptr(rax, rdx); break; + case _and : __ pop_l(rdx); __ andptr(rax, rdx); break; + case _or : __ pop_l(rdx); __ orptr (rax, rdx); break; + case _xor : __ pop_l(rdx); __ xorptr(rax, rdx); break; + default : ShouldNotReachHere(); + } +#else + __ pop_l(rbx, rcx); + switch (op) { + case add : __ addl(rax, rbx); __ adcl(rdx, rcx); break; + case sub : __ subl(rbx, rax); __ sbbl(rcx, rdx); + __ mov (rax, rbx); __ mov (rdx, rcx); break; + case _and : __ andl(rax, rbx); __ andl(rdx, rcx); break; + case _or : __ orl (rax, rbx); __ orl (rdx, rcx); break; + case _xor : __ xorl(rax, rbx); __ xorl(rdx, rcx); break; + default : ShouldNotReachHere(); + } +#endif +} + +void TemplateTable::idiv() { + transition(itos, itos); + __ movl(rcx, rax); + __ pop_i(rax); + // Note: could xor rax and ecx and compare with (-1 ^ min_int). If + // they are not equal, one could do a normal division (no correction + // needed), which may speed up this implementation for the common case. + // (see also JVM spec., p.243 & p.271) + __ corrected_idivl(rcx); +} + +void TemplateTable::irem() { + transition(itos, itos); + __ movl(rcx, rax); + __ pop_i(rax); + // Note: could xor rax and ecx and compare with (-1 ^ min_int). If + // they are not equal, one could do a normal division (no correction + // needed), which may speed up this implementation for the common case. + // (see also JVM spec., p.243 & p.271) + __ corrected_idivl(rcx); + __ movl(rax, rdx); +} + +void TemplateTable::lmul() { + transition(ltos, ltos); +#ifdef _LP64 + __ pop_l(rdx); + __ imulq(rax, rdx); +#else + __ pop_l(rbx, rcx); + __ push(rcx); __ push(rbx); + __ push(rdx); __ push(rax); + __ lmul(2 * wordSize, 0); + __ addptr(rsp, 4 * wordSize); // take off temporaries +#endif +} + +void TemplateTable::ldiv() { + transition(ltos, ltos); +#ifdef _LP64 + __ mov(rcx, rax); + __ pop_l(rax); + // generate explicit div0 check + __ testq(rcx, rcx); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + // Note: could xor rax and rcx and compare with (-1 ^ min_int). If + // they are not equal, one could do a normal division (no correction + // needed), which may speed up this implementation for the common case. + // (see also JVM spec., p.243 & p.271) + __ corrected_idivq(rcx); // kills rbx +#else + __ pop_l(rbx, rcx); + __ push(rcx); __ push(rbx); + __ push(rdx); __ push(rax); + // check if y = 0 + __ orl(rax, rdx); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); + __ addptr(rsp, 4 * wordSize); // take off temporaries +#endif +} + +void TemplateTable::lrem() { + transition(ltos, ltos); +#ifdef _LP64 + __ mov(rcx, rax); + __ pop_l(rax); + __ testq(rcx, rcx); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + // Note: could xor rax and rcx and compare with (-1 ^ min_int). If + // they are not equal, one could do a normal division (no correction + // needed), which may speed up this implementation for the common case. + // (see also JVM spec., p.243 & p.271) + __ corrected_idivq(rcx); // kills rbx + __ mov(rax, rdx); +#else + __ pop_l(rbx, rcx); + __ push(rcx); __ push(rbx); + __ push(rdx); __ push(rax); + // check if y = 0 + __ orl(rax, rdx); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); + __ addptr(rsp, 4 * wordSize); +#endif +} + +void TemplateTable::lshl() { + transition(itos, ltos); + __ movl(rcx, rax); // get shift count + #ifdef _LP64 + __ pop_l(rax); // get shift value + __ shlq(rax); +#else + __ pop_l(rax, rdx); // get shift value + __ lshl(rdx, rax); +#endif +} + +void TemplateTable::lshr() { +#ifdef _LP64 + transition(itos, ltos); + __ movl(rcx, rax); // get shift count + __ pop_l(rax); // get shift value + __ sarq(rax); +#else + transition(itos, ltos); + __ mov(rcx, rax); // get shift count + __ pop_l(rax, rdx); // get shift value + __ lshr(rdx, rax, true); +#endif +} + +void TemplateTable::lushr() { + transition(itos, ltos); +#ifdef _LP64 + __ movl(rcx, rax); // get shift count + __ pop_l(rax); // get shift value + __ shrq(rax); +#else + __ mov(rcx, rax); // get shift count + __ pop_l(rax, rdx); // get shift value + __ lshr(rdx, rax); +#endif +} + +void TemplateTable::fop2(Operation op) { + transition(ftos, ftos); +#ifdef _LP64 + switch (op) { + case add: + __ addss(xmm0, at_rsp()); + __ addptr(rsp, Interpreter::stackElementSize); + break; + case sub: + __ movflt(xmm1, xmm0); + __ pop_f(xmm0); + __ subss(xmm0, xmm1); + break; + case mul: + __ mulss(xmm0, at_rsp()); + __ addptr(rsp, Interpreter::stackElementSize); + break; + case div: + __ movflt(xmm1, xmm0); + __ pop_f(xmm0); + __ divss(xmm0, xmm1); + break; + case rem: + __ movflt(xmm1, xmm0); + __ pop_f(xmm0); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::frem), 2); + break; + default: + ShouldNotReachHere(); + break; + } +#else + switch (op) { + case add: __ fadd_s (at_rsp()); break; + case sub: __ fsubr_s(at_rsp()); break; + case mul: __ fmul_s (at_rsp()); break; + case div: __ fdivr_s(at_rsp()); break; + case rem: __ fld_s (at_rsp()); __ fremr(rax); break; + default : ShouldNotReachHere(); + } + __ f2ieee(); + __ pop(rax); // pop float thing off +#endif +} + +void TemplateTable::dop2(Operation op) { + transition(dtos, dtos); +#ifdef _LP64 + switch (op) { + case add: + __ addsd(xmm0, at_rsp()); + __ addptr(rsp, 2 * Interpreter::stackElementSize); + break; + case sub: + __ movdbl(xmm1, xmm0); + __ pop_d(xmm0); + __ subsd(xmm0, xmm1); + break; + case mul: + __ mulsd(xmm0, at_rsp()); + __ addptr(rsp, 2 * Interpreter::stackElementSize); + break; + case div: + __ movdbl(xmm1, xmm0); + __ pop_d(xmm0); + __ divsd(xmm0, xmm1); + break; + case rem: + __ movdbl(xmm1, xmm0); + __ pop_d(xmm0); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::drem), 2); + break; + default: + ShouldNotReachHere(); + break; + } +#else + switch (op) { + case add: __ fadd_d (at_rsp()); break; + case sub: __ fsubr_d(at_rsp()); break; + case mul: { + Label L_strict; + Label L_join; + const Address access_flags (rcx, Method::access_flags_offset()); + __ get_method(rcx); + __ movl(rcx, access_flags); + __ testl(rcx, JVM_ACC_STRICT); + __ jccb(Assembler::notZero, L_strict); + __ fmul_d (at_rsp()); + __ jmpb(L_join); + __ bind(L_strict); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); + __ fmulp(); + __ fmul_d (at_rsp()); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); + __ fmulp(); + __ bind(L_join); + break; + } + case div: { + Label L_strict; + Label L_join; + const Address access_flags (rcx, Method::access_flags_offset()); + __ get_method(rcx); + __ movl(rcx, access_flags); + __ testl(rcx, JVM_ACC_STRICT); + __ jccb(Assembler::notZero, L_strict); + __ fdivr_d(at_rsp()); + __ jmp(L_join); + __ bind(L_strict); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); + __ fmul_d (at_rsp()); + __ fdivrp(); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); + __ fmulp(); + __ bind(L_join); + break; + } + case rem: __ fld_d (at_rsp()); __ fremr(rax); break; + default : ShouldNotReachHere(); + } + __ d2ieee(); + // Pop double precision number from rsp. + __ pop(rax); + __ pop(rdx); +#endif +} + +void TemplateTable::ineg() { + transition(itos, itos); + __ negl(rax); +} + +void TemplateTable::lneg() { + transition(ltos, ltos); + LP64_ONLY(__ negq(rax)); + NOT_LP64(__ lneg(rdx, rax)); +} + +#ifdef _LP64 +// Note: 'double' and 'long long' have 32-bits alignment on x86. +static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) { + // Use the expression (adr)&(~0xF) to provide 128-bits aligned address + // of 128-bits operands for SSE instructions. + jlong *operand = (jlong*)(((intptr_t)adr)&((intptr_t)(~0xF))); + // Store the value to a 128-bits operand. + operand[0] = lo; + operand[1] = hi; + return operand; +} + +// Buffer for 128-bits masks used by SSE instructions. +static jlong float_signflip_pool[2*2]; +static jlong double_signflip_pool[2*2]; +#endif + +void TemplateTable::fneg() { + transition(ftos, ftos); +#ifdef _LP64 + static jlong *float_signflip = double_quadword(&float_signflip_pool[1], 0x8000000080000000, 0x8000000080000000); + __ xorps(xmm0, ExternalAddress((address) float_signflip)); +#else + __ fchs(); +#endif +} + +void TemplateTable::dneg() { + transition(dtos, dtos); +#ifdef _LP64 + static jlong *double_signflip = double_quadword(&double_signflip_pool[1], 0x8000000000000000, 0x8000000000000000); + __ xorpd(xmm0, ExternalAddress((address) double_signflip)); +#else + __ fchs(); +#endif +} + +void TemplateTable::iinc() { + transition(vtos, vtos); + __ load_signed_byte(rdx, at_bcp(2)); // get constant + locals_index(rbx); + __ addl(iaddress(rbx), rdx); +} + +void TemplateTable::wide_iinc() { + transition(vtos, vtos); + __ movl(rdx, at_bcp(4)); // get constant + locals_index_wide(rbx); + __ bswapl(rdx); // swap bytes & sign-extend constant + __ sarl(rdx, 16); + __ addl(iaddress(rbx), rdx); + // Note: should probably use only one movl to get both + // the index and the constant -> fix this +} + +void TemplateTable::convert() { +#ifdef _LP64 + // Checking +#ifdef ASSERT + { + TosState tos_in = ilgl; + TosState tos_out = ilgl; + switch (bytecode()) { + case Bytecodes::_i2l: // fall through + case Bytecodes::_i2f: // fall through + case Bytecodes::_i2d: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_in = itos; break; + case Bytecodes::_l2i: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_l2d: tos_in = ltos; break; + case Bytecodes::_f2i: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_f2d: tos_in = ftos; break; + case Bytecodes::_d2i: // fall through + case Bytecodes::_d2l: // fall through + case Bytecodes::_d2f: tos_in = dtos; break; + default : ShouldNotReachHere(); + } + switch (bytecode()) { + case Bytecodes::_l2i: // fall through + case Bytecodes::_f2i: // fall through + case Bytecodes::_d2i: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_out = itos; break; + case Bytecodes::_i2l: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_d2l: tos_out = ltos; break; + case Bytecodes::_i2f: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_d2f: tos_out = ftos; break; + case Bytecodes::_i2d: // fall through + case Bytecodes::_l2d: // fall through + case Bytecodes::_f2d: tos_out = dtos; break; + default : ShouldNotReachHere(); + } + transition(tos_in, tos_out); + } +#endif // ASSERT + + static const int64_t is_nan = 0x8000000000000000L; + + // Conversion + switch (bytecode()) { + case Bytecodes::_i2l: + __ movslq(rax, rax); + break; + case Bytecodes::_i2f: + __ cvtsi2ssl(xmm0, rax); + break; + case Bytecodes::_i2d: + __ cvtsi2sdl(xmm0, rax); + break; + case Bytecodes::_i2b: + __ movsbl(rax, rax); + break; + case Bytecodes::_i2c: + __ movzwl(rax, rax); + break; + case Bytecodes::_i2s: + __ movswl(rax, rax); + break; + case Bytecodes::_l2i: + __ movl(rax, rax); + break; + case Bytecodes::_l2f: + __ cvtsi2ssq(xmm0, rax); + break; + case Bytecodes::_l2d: + __ cvtsi2sdq(xmm0, rax); + break; + case Bytecodes::_f2i: + { + Label L; + __ cvttss2sil(rax, xmm0); + __ cmpl(rax, 0x80000000); // NaN or overflow/underflow? + __ jcc(Assembler::notEqual, L); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); + __ bind(L); + } + break; + case Bytecodes::_f2l: + { + Label L; + __ cvttss2siq(rax, xmm0); + // NaN or overflow/underflow? + __ cmp64(rax, ExternalAddress((address) &is_nan)); + __ jcc(Assembler::notEqual, L); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); + __ bind(L); + } + break; + case Bytecodes::_f2d: + __ cvtss2sd(xmm0, xmm0); + break; + case Bytecodes::_d2i: + { + Label L; + __ cvttsd2sil(rax, xmm0); + __ cmpl(rax, 0x80000000); // NaN or overflow/underflow? + __ jcc(Assembler::notEqual, L); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 1); + __ bind(L); + } + break; + case Bytecodes::_d2l: + { + Label L; + __ cvttsd2siq(rax, xmm0); + // NaN or overflow/underflow? + __ cmp64(rax, ExternalAddress((address) &is_nan)); + __ jcc(Assembler::notEqual, L); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 1); + __ bind(L); + } + break; + case Bytecodes::_d2f: + __ cvtsd2ss(xmm0, xmm0); + break; + default: + ShouldNotReachHere(); + } +#else + // Checking +#ifdef ASSERT + { TosState tos_in = ilgl; + TosState tos_out = ilgl; + switch (bytecode()) { + case Bytecodes::_i2l: // fall through + case Bytecodes::_i2f: // fall through + case Bytecodes::_i2d: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_in = itos; break; + case Bytecodes::_l2i: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_l2d: tos_in = ltos; break; + case Bytecodes::_f2i: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_f2d: tos_in = ftos; break; + case Bytecodes::_d2i: // fall through + case Bytecodes::_d2l: // fall through + case Bytecodes::_d2f: tos_in = dtos; break; + default : ShouldNotReachHere(); + } + switch (bytecode()) { + case Bytecodes::_l2i: // fall through + case Bytecodes::_f2i: // fall through + case Bytecodes::_d2i: // fall through + case Bytecodes::_i2b: // fall through + case Bytecodes::_i2c: // fall through + case Bytecodes::_i2s: tos_out = itos; break; + case Bytecodes::_i2l: // fall through + case Bytecodes::_f2l: // fall through + case Bytecodes::_d2l: tos_out = ltos; break; + case Bytecodes::_i2f: // fall through + case Bytecodes::_l2f: // fall through + case Bytecodes::_d2f: tos_out = ftos; break; + case Bytecodes::_i2d: // fall through + case Bytecodes::_l2d: // fall through + case Bytecodes::_f2d: tos_out = dtos; break; + default : ShouldNotReachHere(); + } + transition(tos_in, tos_out); + } +#endif // ASSERT + + // Conversion + // (Note: use push(rcx)/pop(rcx) for 1/2-word stack-ptr manipulation) + switch (bytecode()) { + case Bytecodes::_i2l: + __ extend_sign(rdx, rax); + break; + case Bytecodes::_i2f: + __ push(rax); // store int on tos + __ fild_s(at_rsp()); // load int to ST0 + __ f2ieee(); // truncate to float size + __ pop(rcx); // adjust rsp + break; + case Bytecodes::_i2d: + __ push(rax); // add one slot for d2ieee() + __ push(rax); // store int on tos + __ fild_s(at_rsp()); // load int to ST0 + __ d2ieee(); // truncate to double size + __ pop(rcx); // adjust rsp + __ pop(rcx); + break; + case Bytecodes::_i2b: + __ shll(rax, 24); // truncate upper 24 bits + __ sarl(rax, 24); // and sign-extend byte + LP64_ONLY(__ movsbl(rax, rax)); + break; + case Bytecodes::_i2c: + __ andl(rax, 0xFFFF); // truncate upper 16 bits + LP64_ONLY(__ movzwl(rax, rax)); + break; + case Bytecodes::_i2s: + __ shll(rax, 16); // truncate upper 16 bits + __ sarl(rax, 16); // and sign-extend short + LP64_ONLY(__ movswl(rax, rax)); + break; + case Bytecodes::_l2i: + /* nothing to do */ + break; + case Bytecodes::_l2f: + __ push(rdx); // store long on tos + __ push(rax); + __ fild_d(at_rsp()); // load long to ST0 + __ f2ieee(); // truncate to float size + __ pop(rcx); // adjust rsp + __ pop(rcx); + break; + case Bytecodes::_l2d: + __ push(rdx); // store long on tos + __ push(rax); + __ fild_d(at_rsp()); // load long to ST0 + __ d2ieee(); // truncate to double size + __ pop(rcx); // adjust rsp + __ pop(rcx); + break; + case Bytecodes::_f2i: + __ push(rcx); // reserve space for argument + __ fstp_s(at_rsp()); // pass float argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); + break; + case Bytecodes::_f2l: + __ push(rcx); // reserve space for argument + __ fstp_s(at_rsp()); // pass float argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); + break; + case Bytecodes::_f2d: + /* nothing to do */ + break; + case Bytecodes::_d2i: + __ push(rcx); // reserve space for argument + __ push(rcx); + __ fstp_d(at_rsp()); // pass double argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 2); + break; + case Bytecodes::_d2l: + __ push(rcx); // reserve space for argument + __ push(rcx); + __ fstp_d(at_rsp()); // pass double argument on stack + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 2); + break; + case Bytecodes::_d2f: + __ push(rcx); // reserve space for f2ieee() + __ f2ieee(); // truncate to float size + __ pop(rcx); // adjust rsp + break; + default : + ShouldNotReachHere(); + } +#endif +} + +void TemplateTable::lcmp() { + transition(ltos, itos); +#ifdef _LP64 + Label done; + __ pop_l(rdx); + __ cmpq(rdx, rax); + __ movl(rax, -1); + __ jccb(Assembler::less, done); + __ setb(Assembler::notEqual, rax); + __ movzbl(rax, rax); + __ bind(done); +#else + + // y = rdx:rax + __ pop_l(rbx, rcx); // get x = rcx:rbx + __ lcmp2int(rcx, rbx, rdx, rax);// rcx := cmp(x, y) + __ mov(rax, rcx); +#endif +} + +void TemplateTable::float_cmp(bool is_float, int unordered_result) { +#ifdef _LP64 + Label done; + if (is_float) { + // XXX get rid of pop here, use ... reg, mem32 + __ pop_f(xmm1); + __ ucomiss(xmm1, xmm0); + } else { + // XXX get rid of pop here, use ... reg, mem64 + __ pop_d(xmm1); + __ ucomisd(xmm1, xmm0); + } + if (unordered_result < 0) { + __ movl(rax, -1); + __ jccb(Assembler::parity, done); + __ jccb(Assembler::below, done); + __ setb(Assembler::notEqual, rdx); + __ movzbl(rax, rdx); + } else { + __ movl(rax, 1); + __ jccb(Assembler::parity, done); + __ jccb(Assembler::above, done); + __ movl(rax, 0); + __ jccb(Assembler::equal, done); + __ decrementl(rax); + } + __ bind(done); +#else + if (is_float) { + __ fld_s(at_rsp()); + } else { + __ fld_d(at_rsp()); + __ pop(rdx); + } + __ pop(rcx); + __ fcmp2int(rax, unordered_result < 0); +#endif +} + +void TemplateTable::branch(bool is_jsr, bool is_wide) { + __ get_method(rcx); // rcx holds method + __ profile_taken_branch(rax, rbx); // rax holds updated MDP, rbx + // holds bumped taken count + + const ByteSize be_offset = MethodCounters::backedge_counter_offset() + + InvocationCounter::counter_offset(); + const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + + InvocationCounter::counter_offset(); + + // Load up edx with the branch displacement + if (is_wide) { + __ movl(rdx, at_bcp(1)); + } else { + __ load_signed_short(rdx, at_bcp(1)); + } + __ bswapl(rdx); + + if (!is_wide) { + __ sarl(rdx, 16); + } + LP64_ONLY(__ movl2ptr(rdx, rdx)); + + // Handle all the JSR stuff here, then exit. + // It's much shorter and cleaner than intermingling with the non-JSR + // normal-branch stuff occurring below. + if (is_jsr) { + // Pre-load the next target bytecode into rbx + __ load_unsigned_byte(rbx, Address(rbcp, rdx, Address::times_1, 0)); + + // compute return address as bci in rax + __ lea(rax, at_bcp((is_wide ? 5 : 3) - + in_bytes(ConstMethod::codes_offset()))); + __ subptr(rax, Address(rcx, Method::const_offset())); + // Adjust the bcp in r13 by the displacement in rdx + __ addptr(rbcp, rdx); + // jsr returns atos that is not an oop + __ push_i(rax); + __ dispatch_only(vtos); + return; + } + + // Normal (non-jsr) branch handling + + // Adjust the bcp in r13 by the displacement in rdx + __ addptr(rbcp, rdx); + + assert(UseLoopCounter || !UseOnStackReplacement, + "on-stack-replacement requires loop counters"); + Label backedge_counter_overflow; + Label profile_method; + Label dispatch; + if (UseLoopCounter) { + // increment backedge counter for backward branches + // rax: MDO + // rbx: MDO bumped taken-count + // rcx: method + // rdx: target offset + // r13: target bcp + // r14: locals pointer + __ testl(rdx, rdx); // check if forward or backward branch + __ jcc(Assembler::positive, dispatch); // count only if backward branch + + // check if MethodCounters exists + Label has_counters; + __ movptr(rax, Address(rcx, Method::method_counters_offset())); + __ testptr(rax, rax); + __ jcc(Assembler::notZero, has_counters); + __ push(rdx); + __ push(rcx); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), + rcx); + __ pop(rcx); + __ pop(rdx); + __ movptr(rax, Address(rcx, Method::method_counters_offset())); + __ jcc(Assembler::zero, dispatch); + __ bind(has_counters); + + if (TieredCompilation) { + Label no_mdo; + int increment = InvocationCounter::count_increment; + if (ProfileInterpreter) { + // Are we profiling? + __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset()))); + __ testptr(rbx, rbx); + __ jccb(Assembler::zero, no_mdo); + // Increment the MDO backedge counter + const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) + + in_bytes(InvocationCounter::counter_offset())); + const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset())); + __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, + rax, false, Assembler::zero, &backedge_counter_overflow); + __ jmp(dispatch); + } + __ bind(no_mdo); + // Increment backedge counter in MethodCounters* + __ movptr(rcx, Address(rcx, Method::method_counters_offset())); + const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); + __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask, + rax, false, Assembler::zero, &backedge_counter_overflow); + } else { // not TieredCompilation + // increment counter + __ movptr(rcx, Address(rcx, Method::method_counters_offset())); + __ movl(rax, Address(rcx, be_offset)); // load backedge counter + __ incrementl(rax, InvocationCounter::count_increment); // increment counter + __ movl(Address(rcx, be_offset), rax); // store counter + + __ movl(rax, Address(rcx, inv_offset)); // load invocation counter + + __ andl(rax, InvocationCounter::count_mask_value); // and the status bits + __ addl(rax, Address(rcx, be_offset)); // add both counters + + if (ProfileInterpreter) { + // Test to see if we should create a method data oop + __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); + __ jcc(Assembler::less, dispatch); + + // if no method data exists, go to profile method + __ test_method_data_pointer(rax, profile_method); + + if (UseOnStackReplacement) { + // check for overflow against rbx which is the MDO taken count + __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); + __ jcc(Assembler::below, dispatch); + + // When ProfileInterpreter is on, the backedge_count comes + // from the MethodData*, which value does not get reset on + // the call to frequency_counter_overflow(). To avoid + // excessive calls to the overflow routine while the method is + // being compiled, add a second test to make sure the overflow + // function is called only once every overflow_frequency. + const int overflow_frequency = 1024; + __ andl(rbx, overflow_frequency - 1); + __ jcc(Assembler::zero, backedge_counter_overflow); + + } + } else { + if (UseOnStackReplacement) { + // check for overflow against rax, which is the sum of the + // counters + __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); + __ jcc(Assembler::aboveEqual, backedge_counter_overflow); + + } + } + } + __ bind(dispatch); + } + + // Pre-load the next target bytecode into rbx + __ load_unsigned_byte(rbx, Address(rbcp, 0)); + + // continue with the bytecode @ target + // rax: return bci for jsr's, unused otherwise + // rbx: target bytecode + // r13: target bcp + __ dispatch_only(vtos); + + if (UseLoopCounter) { + if (ProfileInterpreter) { + // Out-of-line code to allocate method data oop. + __ bind(profile_method); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); + __ load_unsigned_byte(rbx, Address(rbcp, 0)); // restore target bytecode + __ set_method_data_pointer_for_bcp(); + __ jmp(dispatch); + } + + if (UseOnStackReplacement) { + // invocation counter overflow + __ bind(backedge_counter_overflow); + __ negptr(rdx); + __ addptr(rdx, rbcp); // branch bcp + // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::frequency_counter_overflow), + rdx); + __ load_unsigned_byte(rbx, Address(rbcp, 0)); // restore target bytecode + + // rax: osr nmethod (osr ok) or NULL (osr not possible) + // rbx: target bytecode + // rdx: scratch + // r14: locals pointer + // r13: bcp + __ testptr(rax, rax); // test result + __ jcc(Assembler::zero, dispatch); // no osr if null + // nmethod may have been invalidated (VM may block upon call_VM return) + __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use); + __ jcc(Assembler::notEqual, dispatch); + + // We have the address of an on stack replacement routine in rax + // We need to prepare to execute the OSR method. First we must + // migrate the locals and monitors off of the stack. + + LP64_ONLY(__ mov(r13, rax)); // save the nmethod + NOT_LP64(__ mov(rbx, rax)); // save the nmethod + NOT_LP64(__ get_thread(rcx)); + + call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); + + // rax is OSR buffer, move it to expected parameter location + LP64_ONLY(__ mov(j_rarg0, rax)); + NOT_LP64(__ mov(rcx, rax)); + // We use j_rarg definitions here so that registers don't conflict as parameter + // registers change across platforms as we are in the midst of a calling + // sequence to the OSR nmethod and we don't want collision. These are NOT parameters. + + const Register retaddr = LP64_ONLY(j_rarg2) NOT_LP64(rdi); + const Register sender_sp = LP64_ONLY(j_rarg1) NOT_LP64(rdx); + + + // pop the interpreter frame + __ movptr(sender_sp, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp + __ leave(); // remove frame anchor + __ pop(retaddr); // get return address + __ mov(rsp, sender_sp); // set sp to sender sp + // Ensure compiled code always sees stack at proper alignment + __ andptr(rsp, -(StackAlignmentInBytes)); + + // unlike x86 we need no specialized return from compiled code + // to the interpreter or the call stub. + + // push the return address + __ push(retaddr); + + // and begin the OSR nmethod + LP64_ONLY(__ jmp(Address(r13, nmethod::osr_entry_point_offset()))); + NOT_LP64(__ jmp(Address(rbx, nmethod::osr_entry_point_offset()))); + } + } +} + +void TemplateTable::if_0cmp(Condition cc) { + transition(itos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + __ testl(rax, rax); + __ jcc(j_not(cc), not_taken); + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(rax); +} + +void TemplateTable::if_icmp(Condition cc) { + transition(itos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + __ pop_i(rdx); + __ cmpl(rdx, rax); + __ jcc(j_not(cc), not_taken); + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(rax); +} + +void TemplateTable::if_nullcmp(Condition cc) { + transition(atos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + __ testptr(rax, rax); + __ jcc(j_not(cc), not_taken); + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(rax); +} + +void TemplateTable::if_acmp(Condition cc) { + transition(atos, vtos); + // assume branch is more often taken than not (loops use backward branches) + Label not_taken; + __ pop_ptr(rdx); + __ cmpptr(rdx, rax); + __ jcc(j_not(cc), not_taken); + branch(false, false); + __ bind(not_taken); + __ profile_not_taken_branch(rax); +} + +void TemplateTable::ret() { + transition(vtos, vtos); + locals_index(rbx); + LP64_ONLY(__ movslq(rbx, iaddress(rbx))); // get return bci, compute return bcp + NOT_LP64(__ movptr(rbx, iaddress(rbx))); + __ profile_ret(rbx, rcx); + __ get_method(rax); + __ movptr(rbcp, Address(rax, Method::const_offset())); + __ lea(rbcp, Address(rbcp, rbx, Address::times_1, + ConstMethod::codes_offset())); + __ dispatch_next(vtos); +} + +void TemplateTable::wide_ret() { + transition(vtos, vtos); + locals_index_wide(rbx); + __ movptr(rbx, aaddress(rbx)); // get return bci, compute return bcp + __ profile_ret(rbx, rcx); + __ get_method(rax); + __ movptr(rbcp, Address(rax, Method::const_offset())); + __ lea(rbcp, Address(rbcp, rbx, Address::times_1, ConstMethod::codes_offset())); + __ dispatch_next(vtos); +} + +void TemplateTable::tableswitch() { + Label default_case, continue_execution; + transition(itos, vtos); + + // align r13/rsi + __ lea(rbx, at_bcp(BytesPerInt)); + __ andptr(rbx, -BytesPerInt); + // load lo & hi + __ movl(rcx, Address(rbx, BytesPerInt)); + __ movl(rdx, Address(rbx, 2 * BytesPerInt)); + __ bswapl(rcx); + __ bswapl(rdx); + // check against lo & hi + __ cmpl(rax, rcx); + __ jcc(Assembler::less, default_case); + __ cmpl(rax, rdx); + __ jcc(Assembler::greater, default_case); + // lookup dispatch offset + __ subl(rax, rcx); + __ movl(rdx, Address(rbx, rax, Address::times_4, 3 * BytesPerInt)); + __ profile_switch_case(rax, rbx, rcx); + // continue execution + __ bind(continue_execution); + __ bswapl(rdx); + LP64_ONLY(__ movl2ptr(rdx, rdx)); + __ load_unsigned_byte(rbx, Address(rbcp, rdx, Address::times_1)); + __ addptr(rbcp, rdx); + __ dispatch_only(vtos); + // handle default + __ bind(default_case); + __ profile_switch_default(rax); + __ movl(rdx, Address(rbx, 0)); + __ jmp(continue_execution); +} + +void TemplateTable::lookupswitch() { + transition(itos, itos); + __ stop("lookupswitch bytecode should have been rewritten"); +} + +void TemplateTable::fast_linearswitch() { + transition(itos, vtos); + Label loop_entry, loop, found, continue_execution; + // bswap rax so we can avoid bswapping the table entries + __ bswapl(rax); + // align r13 + __ lea(rbx, at_bcp(BytesPerInt)); // btw: should be able to get rid of + // this instruction (change offsets + // below) + __ andptr(rbx, -BytesPerInt); + // set counter + __ movl(rcx, Address(rbx, BytesPerInt)); + __ bswapl(rcx); + __ jmpb(loop_entry); + // table search + __ bind(loop); + __ cmpl(rax, Address(rbx, rcx, Address::times_8, 2 * BytesPerInt)); + __ jcc(Assembler::equal, found); + __ bind(loop_entry); + __ decrementl(rcx); + __ jcc(Assembler::greaterEqual, loop); + // default case + __ profile_switch_default(rax); + __ movl(rdx, Address(rbx, 0)); + __ jmp(continue_execution); + // entry found -> get offset + __ bind(found); + __ movl(rdx, Address(rbx, rcx, Address::times_8, 3 * BytesPerInt)); + __ profile_switch_case(rcx, rax, rbx); + // continue execution + __ bind(continue_execution); + __ bswapl(rdx); + __ movl2ptr(rdx, rdx); + __ load_unsigned_byte(rbx, Address(rbcp, rdx, Address::times_1)); + __ addptr(rbcp, rdx); + __ dispatch_only(vtos); +} + +void TemplateTable::fast_binaryswitch() { + transition(itos, vtos); + // Implementation using the following core algorithm: + // + // int binary_search(int key, LookupswitchPair* array, int n) { + // // Binary search according to "Methodik des Programmierens" by + // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985. + // int i = 0; + // int j = n; + // while (i+1 < j) { + // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q) + // // with Q: for all i: 0 <= i < n: key < a[i] + // // where a stands for the array and assuming that the (inexisting) + // // element a[n] is infinitely big. + // int h = (i + j) >> 1; + // // i < h < j + // if (key < array[h].fast_match()) { + // j = h; + // } else { + // i = h; + // } + // } + // // R: a[i] <= key < a[i+1] or Q + // // (i.e., if key is within array, i is the correct index) + // return i; + // } + + // Register allocation + const Register key = rax; // already set (tosca) + const Register array = rbx; + const Register i = rcx; + const Register j = rdx; + const Register h = rdi; + const Register temp = rsi; + + // Find array start + NOT_LP64(__ save_bcp()); + + __ lea(array, at_bcp(3 * BytesPerInt)); // btw: should be able to + // get rid of this + // instruction (change + // offsets below) + __ andptr(array, -BytesPerInt); + + // Initialize i & j + __ xorl(i, i); // i = 0; + __ movl(j, Address(array, -BytesPerInt)); // j = length(array); + + // Convert j into native byteordering + __ bswapl(j); + + // And start + Label entry; + __ jmp(entry); + + // binary search loop + { + Label loop; + __ bind(loop); + // int h = (i + j) >> 1; + __ leal(h, Address(i, j, Address::times_1)); // h = i + j; + __ sarl(h, 1); // h = (i + j) >> 1; + // if (key < array[h].fast_match()) { + // j = h; + // } else { + // i = h; + // } + // Convert array[h].match to native byte-ordering before compare + __ movl(temp, Address(array, h, Address::times_8)); + __ bswapl(temp); + __ cmpl(key, temp); + // j = h if (key < array[h].fast_match()) + __ cmov32(Assembler::less, j, h); + // i = h if (key >= array[h].fast_match()) + __ cmov32(Assembler::greaterEqual, i, h); + // while (i+1 < j) + __ bind(entry); + __ leal(h, Address(i, 1)); // i+1 + __ cmpl(h, j); // i+1 < j + __ jcc(Assembler::less, loop); + } + + // end of binary search, result index is i (must check again!) + Label default_case; + // Convert array[i].match to native byte-ordering before compare + __ movl(temp, Address(array, i, Address::times_8)); + __ bswapl(temp); + __ cmpl(key, temp); + __ jcc(Assembler::notEqual, default_case); + + // entry found -> j = offset + __ movl(j , Address(array, i, Address::times_8, BytesPerInt)); + __ profile_switch_case(i, key, array); + __ bswapl(j); + LP64_ONLY(__ movslq(j, j)); + + NOT_LP64(__ restore_bcp()); + NOT_LP64(__ restore_locals()); // restore rdi + + __ load_unsigned_byte(rbx, Address(rbcp, j, Address::times_1)); + __ addptr(rbcp, j); + __ dispatch_only(vtos); + + // default case -> j = default offset + __ bind(default_case); + __ profile_switch_default(i); + __ movl(j, Address(array, -2 * BytesPerInt)); + __ bswapl(j); + LP64_ONLY(__ movslq(j, j)); + + NOT_LP64(__ restore_bcp()); + NOT_LP64(__ restore_locals()); + + __ load_unsigned_byte(rbx, Address(rbcp, j, Address::times_1)); + __ addptr(rbcp, j); + __ dispatch_only(vtos); +} + +void TemplateTable::_return(TosState state) { + transition(state, state); + + Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); + + assert(_desc->calls_vm(), + "inconsistent calls_vm information"); // call in remove_activation + + if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { + assert(state == vtos, "only valid state"); + __ movptr(robj, aaddress(0)); + __ load_klass(rdi, robj); + __ movl(rdi, Address(rdi, Klass::access_flags_offset())); + __ testl(rdi, JVM_ACC_HAS_FINALIZER); + Label skip_register_finalizer; + __ jcc(Assembler::zero, skip_register_finalizer); + + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), robj); + + __ bind(skip_register_finalizer); + } + + __ remove_activation(state, rbcp); + __ jmp(rbcp); +} + +// ---------------------------------------------------------------------------- +// Volatile variables demand their effects be made known to all CPU's +// in order. Store buffers on most chips allow reads & writes to +// reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode +// without some kind of memory barrier (i.e., it's not sufficient that +// the interpreter does not reorder volatile references, the hardware +// also must not reorder them). +// +// According to the new Java Memory Model (JMM): +// (1) All volatiles are serialized wrt to each other. ALSO reads & +// writes act as aquire & release, so: +// (2) A read cannot let unrelated NON-volatile memory refs that +// happen after the read float up to before the read. It's OK for +// non-volatile memory refs that happen before the volatile read to +// float down below it. +// (3) Similar a volatile write cannot let unrelated NON-volatile +// memory refs that happen BEFORE the write float down to after the +// write. It's OK for non-volatile memory refs that happen after the +// volatile write to float up before it. +// +// We only put in barriers around volatile refs (they are expensive), +// not _between_ memory refs (that would require us to track the +// flavor of the previous memory refs). Requirements (2) and (3) +// require some barriers before volatile stores and after volatile +// loads. These nearly cover requirement (1) but miss the +// volatile-store-volatile-load case. This final case is placed after +// volatile-stores although it could just as well go before +// volatile-loads. + +void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constraint ) { + // Helper function to insert a is-volatile test and memory barrier + if(!os::is_MP()) return; // Not needed on single CPU + __ membar(order_constraint); +} + +void TemplateTable::resolve_cache_and_index(int byte_no, + Register Rcache, + Register index, + size_t index_size) { + const Register temp = rbx; + assert_different_registers(Rcache, index, temp); + + Label resolved; + assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size); + __ cmpl(temp, (int) bytecode()); // have we resolved this bytecode? + __ jcc(Assembler::equal, resolved); + + // resolve first time through + address entry; + switch (bytecode()) { + case Bytecodes::_getstatic : // fall through + case Bytecodes::_putstatic : // fall through + case Bytecodes::_getfield : // fall through + case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; + case Bytecodes::_invokevirtual : // fall through + case Bytecodes::_invokespecial : // fall through + case Bytecodes::_invokestatic : // fall through + case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; + case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break; + case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; + default: + fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); + break; + } + __ movl(temp, (int)bytecode()); + __ call_VM(noreg, entry, temp); + // Update registers with resolved info + __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); + __ bind(resolved); +} + +// The cache and index registers must be set before call +void TemplateTable::load_field_cp_cache_entry(Register obj, + Register cache, + Register index, + Register off, + Register flags, + bool is_static = false) { + assert_different_registers(cache, index, flags, off); + + ByteSize cp_base_offset = ConstantPoolCache::base_offset(); + // Field offset + __ movptr(off, Address(cache, index, Address::times_ptr, + in_bytes(cp_base_offset + + ConstantPoolCacheEntry::f2_offset()))); + // Flags + __ movl(flags, Address(cache, index, Address::times_ptr, + in_bytes(cp_base_offset + + ConstantPoolCacheEntry::flags_offset()))); + + // klass overwrite register + if (is_static) { + __ movptr(obj, Address(cache, index, Address::times_ptr, + in_bytes(cp_base_offset + + ConstantPoolCacheEntry::f1_offset()))); + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + __ movptr(obj, Address(obj, mirror_offset)); + } +} + +void TemplateTable::load_invoke_cp_cache_entry(int byte_no, + Register method, + Register itable_index, + Register flags, + bool is_invokevirtual, + bool is_invokevfinal, /*unused*/ + bool is_invokedynamic) { + // setup registers + const Register cache = rcx; + const Register index = rdx; + assert_different_registers(method, flags); + assert_different_registers(method, cache, index); + assert_different_registers(itable_index, flags); + assert_different_registers(itable_index, cache, index); + // determine constant pool cache field offsets + assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant"); + const int method_offset = in_bytes( + ConstantPoolCache::base_offset() + + ((byte_no == f2_byte) + ? ConstantPoolCacheEntry::f2_offset() + : ConstantPoolCacheEntry::f1_offset())); + const int flags_offset = in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::flags_offset()); + // access constant pool cache fields + const int index_offset = in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()); + + size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); + resolve_cache_and_index(byte_no, cache, index, index_size); + __ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); + + if (itable_index != noreg) { + // pick up itable or appendix index from f2 also: + __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset)); + } + __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); +} + +// The registers cache and index expected to be set before call. +// Correct values of the cache and index registers are preserved. +void TemplateTable::jvmti_post_field_access(Register cache, + Register index, + bool is_static, + bool has_tos) { + if (JvmtiExport::can_post_field_access()) { + // Check to see if a field access watch has been set before we take + // the time to call into the VM. + Label L1; + assert_different_registers(cache, index, rax); + __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); + __ testl(rax,rax); + __ jcc(Assembler::zero, L1); + + // cache entry pointer + __ addptr(cache, in_bytes(ConstantPoolCache::base_offset())); + __ shll(index, LogBytesPerWord); + __ addptr(cache, index); + if (is_static) { + __ xorptr(rax, rax); // NULL object reference + } else { + __ pop(atos); // Get the object + __ verify_oop(rax); + __ push(atos); // Restore stack state + } + // rax,: object pointer or NULL + // cache: cache entry pointer + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), + rax, cache); + __ get_cache_and_index_at_bcp(cache, index, 1); + __ bind(L1); + } +} + +void TemplateTable::pop_and_check_object(Register r) { + __ pop_ptr(r); + __ null_check(r); // for field access must check obj. + __ verify_oop(r); +} + +void TemplateTable::getfield_or_static(int byte_no, bool is_static) { + transition(vtos, vtos); + + const Register cache = rcx; + const Register index = rdx; + const Register obj = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + const Register off = rbx; + const Register flags = rax; + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); // uses same reg as obj, so don't mix them + + resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); + jvmti_post_field_access(cache, index, is_static, false); + load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); + + if (!is_static) pop_and_check_object(obj); + + const Address field(obj, off, Address::times_1, 0*wordSize); + NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize)); + + Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + + __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); + // Make sure we don't need to mask edx after the above shift + assert(btos == 0, "change code, btos != 0"); + + __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); + + __ jcc(Assembler::notZero, notByte); + // btos + __ load_signed_byte(rax, field); + __ push(btos); + // Rewrite bytecode to be faster + if (!is_static) { + patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notByte); + __ cmpl(flags, atos); + __ jcc(Assembler::notEqual, notObj); + // atos + __ load_heap_oop(rax, field); + __ push(atos); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notObj); + __ cmpl(flags, itos); + __ jcc(Assembler::notEqual, notInt); + // itos + __ movl(rax, field); + __ push(itos); + // Rewrite bytecode to be faster + if (!is_static) { + patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notInt); + __ cmpl(flags, ctos); + __ jcc(Assembler::notEqual, notChar); + // ctos + __ load_unsigned_short(rax, field); + __ push(ctos); + // Rewrite bytecode to be faster + if (!is_static) { + patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notChar); + __ cmpl(flags, stos); + __ jcc(Assembler::notEqual, notShort); + // stos + __ load_signed_short(rax, field); + __ push(stos); + // Rewrite bytecode to be faster + if (!is_static) { + patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notShort); + __ cmpl(flags, ltos); + __ jcc(Assembler::notEqual, notLong); + // ltos + +#ifndef _LP64 + // Generate code as if volatile. There just aren't enough registers to + // save that information and this code is faster than the test. + __ fild_d(field); // Must load atomically + __ subptr(rsp,2*wordSize); // Make space for store + __ fistp_d(Address(rsp,0)); + __ pop(rax); + __ pop(rdx); +#else + __ movq(rax, field); +#endif + + __ push(ltos); + // Rewrite bytecode to be faster + LP64_ONLY(if (!is_static) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx)); + __ jmp(Done); + + __ bind(notLong); + __ cmpl(flags, ftos); + __ jcc(Assembler::notEqual, notFloat); + // ftos + + LP64_ONLY(__ movflt(xmm0, field)); + NOT_LP64(__ fld_s(field)); + __ push(ftos); + // Rewrite bytecode to be faster + if (!is_static) { + patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notFloat); +#ifdef ASSERT + __ cmpl(flags, dtos); + __ jcc(Assembler::notEqual, notDouble); +#endif + // dtos + LP64_ONLY(__ movdbl(xmm0, field)); + NOT_LP64(__ fld_d(field)); + __ push(dtos); + // Rewrite bytecode to be faster + if (!is_static) { + patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx); + } +#ifdef ASSERT + __ jmp(Done); + + + __ bind(notDouble); + __ stop("Bad state"); +#endif + + __ bind(Done); + // [jk] not needed currently + // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadLoad | + // Assembler::LoadStore)); +} + +void TemplateTable::getfield(int byte_no) { + getfield_or_static(byte_no, false); +} + +void TemplateTable::getstatic(int byte_no) { + getfield_or_static(byte_no, true); +} + + +// The registers cache and index expected to be set before call. +// The function may destroy various registers, just not the cache and index registers. +void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { + + const Register robj = LP64_ONLY(c_rarg2) NOT_LP64(rax); + const Register RBX = LP64_ONLY(c_rarg1) NOT_LP64(rbx); + const Register RCX = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + const Register RDX = LP64_ONLY(rscratch1) NOT_LP64(rdx); + + ByteSize cp_base_offset = ConstantPoolCache::base_offset(); + + if (JvmtiExport::can_post_field_modification()) { + // Check to see if a field modification watch has been set before + // we take the time to call into the VM. + Label L1; + assert_different_registers(cache, index, rax); + __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); + __ testl(rax, rax); + __ jcc(Assembler::zero, L1); + + __ get_cache_and_index_at_bcp(robj, RDX, 1); + + + if (is_static) { + // Life is simple. Null out the object pointer. + __ xorl(RBX, RBX); + + } else { + // Life is harder. The stack holds the value on top, followed by + // the object. We don't know the size of the value, though; it + // could be one or two words depending on its type. As a result, + // we must find the type to determine where the object is. +#ifndef _LP64 + Label two_word, valsize_known; +#endif + __ movl(RCX, Address(robj, RDX, + Address::times_ptr, + in_bytes(cp_base_offset + + ConstantPoolCacheEntry::flags_offset()))); + NOT_LP64(__ mov(rbx, rsp)); + __ shrl(RCX, ConstantPoolCacheEntry::tos_state_shift); + + // Make sure we don't need to mask rcx after the above shift + ConstantPoolCacheEntry::verify_tos_state_shift(); +#ifdef _LP64 + __ movptr(c_rarg1, at_tos_p1()); // initially assume a one word jvalue + __ cmpl(c_rarg3, ltos); + __ cmovptr(Assembler::equal, + c_rarg1, at_tos_p2()); // ltos (two word jvalue) + __ cmpl(c_rarg3, dtos); + __ cmovptr(Assembler::equal, + c_rarg1, at_tos_p2()); // dtos (two word jvalue) +#else + __ cmpl(rcx, ltos); + __ jccb(Assembler::equal, two_word); + __ cmpl(rcx, dtos); + __ jccb(Assembler::equal, two_word); + __ addptr(rbx, Interpreter::expr_offset_in_bytes(1)); // one word jvalue (not ltos, dtos) + __ jmpb(valsize_known); + + __ bind(two_word); + __ addptr(rbx, Interpreter::expr_offset_in_bytes(2)); // two words jvalue + + __ bind(valsize_known); + // setup object pointer + __ movptr(rbx, Address(rbx, 0)); +#endif + } + // cache entry pointer + __ addptr(robj, in_bytes(cp_base_offset)); + __ shll(RDX, LogBytesPerWord); + __ addptr(robj, RDX); + // object (tos) + __ mov(RCX, rsp); + // c_rarg1: object pointer set up above (NULL if static) + // c_rarg2: cache entry pointer + // c_rarg3: jvalue object on the stack + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_modification), + RBX, robj, RCX); + __ get_cache_and_index_at_bcp(cache, index, 1); + __ bind(L1); + } +} + +void TemplateTable::putfield_or_static(int byte_no, bool is_static) { + transition(vtos, vtos); + + const Register cache = rcx; + const Register index = rdx; + const Register obj = rcx; + const Register off = rbx; + const Register flags = rax; + const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + + resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); + jvmti_post_field_mod(cache, index, is_static); + load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); + + // [jk] not needed currently + // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore | + // Assembler::StoreStore)); + + Label notVolatile, Done; + __ movl(rdx, flags); + __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); + __ andl(rdx, 0x1); + + // field addresses + const Address field(obj, off, Address::times_1, 0*wordSize); + NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);) + + Label notByte, notInt, notShort, notChar, + notLong, notFloat, notObj, notDouble; + + __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); + + assert(btos == 0, "change code, btos != 0"); + __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); + __ jcc(Assembler::notZero, notByte); + + // btos + { + __ pop(btos); + if (!is_static) pop_and_check_object(obj); + __ movb(field, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notByte); + __ cmpl(flags, atos); + __ jcc(Assembler::notEqual, notObj); + + // atos + { + __ pop(atos); + if (!is_static) pop_and_check_object(obj); + // Store into the field + do_oop_store(_masm, field, rax, _bs->kind(), false); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notObj); + __ cmpl(flags, itos); + __ jcc(Assembler::notEqual, notInt); + + // itos + { + __ pop(itos); + if (!is_static) pop_and_check_object(obj); + __ movl(field, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notInt); + __ cmpl(flags, ctos); + __ jcc(Assembler::notEqual, notChar); + + // ctos + { + __ pop(ctos); + if (!is_static) pop_and_check_object(obj); + __ movw(field, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notChar); + __ cmpl(flags, stos); + __ jcc(Assembler::notEqual, notShort); + + // stos + { + __ pop(stos); + if (!is_static) pop_and_check_object(obj); + __ movw(field, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notShort); + __ cmpl(flags, ltos); + __ jcc(Assembler::notEqual, notLong); + + // ltos +#ifdef _LP64 + { + __ pop(ltos); + if (!is_static) pop_and_check_object(obj); + __ movq(field, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } +#else + { + Label notVolatileLong; + __ testl(rdx, rdx); + __ jcc(Assembler::zero, notVolatileLong); + + __ pop(ltos); // overwrites rdx, do this after testing volatile. + if (!is_static) pop_and_check_object(obj); + + // Replace with real volatile test + __ push(rdx); + __ push(rax); // Must update atomically with FIST + __ fild_d(Address(rsp,0)); // So load into FPU register + __ fistp_d(field); // and put into memory atomically + __ addptr(rsp, 2*wordSize); + // volatile_barrier(); + volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | + Assembler::StoreStore)); + // Don't rewrite volatile version + __ jmp(notVolatile); + + __ bind(notVolatileLong); + + __ pop(ltos); // overwrites rdx + if (!is_static) pop_and_check_object(obj); + __ movptr(hi, rdx); + __ movptr(field, rax); + // Don't rewrite to _fast_lputfield for potential volatile case. + __ jmp(notVolatile); + } +#endif // _LP64 + + __ bind(notLong); + __ cmpl(flags, ftos); + __ jcc(Assembler::notEqual, notFloat); + + // ftos + { + __ pop(ftos); + if (!is_static) pop_and_check_object(obj); + NOT_LP64( __ fstp_s(field);) + LP64_ONLY( __ movflt(field, xmm0);) + if (!is_static) { + patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notFloat); +#ifdef ASSERT + __ cmpl(flags, dtos); + __ jcc(Assembler::notEqual, notDouble); +#endif + + // dtos + { + __ pop(dtos); + if (!is_static) pop_and_check_object(obj); + NOT_LP64( __ fstp_d(field);) + LP64_ONLY( __ movdbl(field, xmm0);) + if (!is_static) { + patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no); + } + } + +#ifdef ASSERT + __ jmp(Done); + + __ bind(notDouble); + __ stop("Bad state"); +#endif + + __ bind(Done); + + // Check for volatile store + __ testl(rdx, rdx); + __ jcc(Assembler::zero, notVolatile); + volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | + Assembler::StoreStore)); + __ bind(notVolatile); +} + +void TemplateTable::putfield(int byte_no) { + putfield_or_static(byte_no, false); +} + +void TemplateTable::putstatic(int byte_no) { + putfield_or_static(byte_no, true); +} + +void TemplateTable::jvmti_post_fast_field_mod() { + + const Register scratch = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + + if (JvmtiExport::can_post_field_modification()) { + // Check to see if a field modification watch has been set before + // we take the time to call into the VM. + Label L2; + __ mov32(scratch, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); + __ testl(scratch, scratch); + __ jcc(Assembler::zero, L2); + __ pop_ptr(rbx); // copy the object pointer from tos + __ verify_oop(rbx); + __ push_ptr(rbx); // put the object pointer back on tos + // Save tos values before call_VM() clobbers them. Since we have + // to do it for every data type, we use the saved values as the + // jvalue object. + switch (bytecode()) { // load values into the jvalue object + case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ push_i(rax); break; + case Bytecodes::_fast_dputfield: __ push_d(); break; + case Bytecodes::_fast_fputfield: __ push_f(); break; + case Bytecodes::_fast_lputfield: __ push_l(rax); break; + + default: + ShouldNotReachHere(); + } + __ mov(scratch, rsp); // points to jvalue on the stack + // access constant pool cache entry + LP64_ONLY(__ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1)); + NOT_LP64(__ get_cache_entry_pointer_at_bcp(rax, rdx, 1)); + __ verify_oop(rbx); + // rbx: object pointer copied above + // c_rarg2: cache entry pointer + // c_rarg3: jvalue object on the stack + LP64_ONLY(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, c_rarg2, c_rarg3)); + NOT_LP64(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx)); + + switch (bytecode()) { // restore tos values + case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ pop_i(rax); break; + case Bytecodes::_fast_dputfield: __ pop_d(); break; + case Bytecodes::_fast_fputfield: __ pop_f(); break; + case Bytecodes::_fast_lputfield: __ pop_l(rax); break; + } + __ bind(L2); + } +} + +void TemplateTable::fast_storefield(TosState state) { + transition(state, vtos); + + ByteSize base = ConstantPoolCache::base_offset(); + + jvmti_post_fast_field_mod(); + + // access constant pool cache + __ get_cache_and_index_at_bcp(rcx, rbx, 1); + + // test for volatile with rdx but rdx is tos register for lputfield. + __ movl(rdx, Address(rcx, rbx, Address::times_ptr, + in_bytes(base + + ConstantPoolCacheEntry::flags_offset()))); + + // replace index with field offset from cache entry + __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, + in_bytes(base + ConstantPoolCacheEntry::f2_offset()))); + + // [jk] not needed currently + // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore | + // Assembler::StoreStore)); + + Label notVolatile; + __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); + __ andl(rdx, 0x1); + + // Get object from stack + pop_and_check_object(rcx); + + // field address + const Address field(rcx, rbx, Address::times_1); + + // access field + switch (bytecode()) { + case Bytecodes::_fast_aputfield: + do_oop_store(_masm, field, rax, _bs->kind(), false); + break; + case Bytecodes::_fast_lputfield: +#ifdef _LP64 + __ movq(field, rax); +#else + __ stop("should not be rewritten"); +#endif + break; + case Bytecodes::_fast_iputfield: + __ movl(field, rax); + break; + case Bytecodes::_fast_bputfield: + __ movb(field, rax); + break; + case Bytecodes::_fast_sputfield: + // fall through + case Bytecodes::_fast_cputfield: + __ movw(field, rax); + break; + case Bytecodes::_fast_fputfield: + NOT_LP64( __ fstp_s(field); ) + LP64_ONLY( __ movflt(field, xmm0);) + break; + case Bytecodes::_fast_dputfield: + NOT_LP64( __ fstp_d(field); ) + LP64_ONLY( __ movdbl(field, xmm0);) + break; + default: + ShouldNotReachHere(); + } + + // Check for volatile store + __ testl(rdx, rdx); + __ jcc(Assembler::zero, notVolatile); + volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | + Assembler::StoreStore)); + __ bind(notVolatile); +} + +void TemplateTable::fast_accessfield(TosState state) { + transition(atos, state); + + // Do the JVMTI work here to avoid disturbing the register state below + if (JvmtiExport::can_post_field_access()) { + // Check to see if a field access watch has been set before we + // take the time to call into the VM. + Label L1; + __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); + __ testl(rcx, rcx); + __ jcc(Assembler::zero, L1); + // access constant pool cache entry + LP64_ONLY(__ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1)); + NOT_LP64(__ get_cache_entry_pointer_at_bcp(rcx, rdx, 1)); + __ verify_oop(rax); + __ push_ptr(rax); // save object pointer before call_VM() clobbers it + LP64_ONLY(__ mov(c_rarg1, rax)); + // c_rarg1: object pointer copied above + // c_rarg2: cache entry pointer + LP64_ONLY(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), c_rarg1, c_rarg2)); + NOT_LP64(__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), rax, rcx)); + __ pop_ptr(rax); // restore object pointer + __ bind(L1); + } + + // access constant pool cache + __ get_cache_and_index_at_bcp(rcx, rbx, 1); + // replace index with field offset from cache entry + // [jk] not needed currently + // if (os::is_MP()) { + // __ movl(rdx, Address(rcx, rbx, Address::times_8, + // in_bytes(ConstantPoolCache::base_offset() + + // ConstantPoolCacheEntry::flags_offset()))); + // __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); + // __ andl(rdx, 0x1); + // } + __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, + in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()))); + + // rax: object + __ verify_oop(rax); + __ null_check(rax); + Address field(rax, rbx, Address::times_1); + + // access field + switch (bytecode()) { + case Bytecodes::_fast_agetfield: + __ load_heap_oop(rax, field); + __ verify_oop(rax); + break; + case Bytecodes::_fast_lgetfield: +#ifdef _LP64 + __ movq(rax, field); +#else + __ stop("should not be rewritten"); +#endif + break; + case Bytecodes::_fast_igetfield: + __ movl(rax, field); + break; + case Bytecodes::_fast_bgetfield: + __ movsbl(rax, field); + break; + case Bytecodes::_fast_sgetfield: + __ load_signed_short(rax, field); + break; + case Bytecodes::_fast_cgetfield: + __ load_unsigned_short(rax, field); + break; + case Bytecodes::_fast_fgetfield: + LP64_ONLY(__ movflt(xmm0, field)); + NOT_LP64(__ fld_s(field)); + break; + case Bytecodes::_fast_dgetfield: + LP64_ONLY(__ movdbl(xmm0, field)); + NOT_LP64(__ fld_d(field)); + break; + default: + ShouldNotReachHere(); + } + // [jk] not needed currently + // if (os::is_MP()) { + // Label notVolatile; + // __ testl(rdx, rdx); + // __ jcc(Assembler::zero, notVolatile); + // __ membar(Assembler::LoadLoad); + // __ bind(notVolatile); + //}; +} + +void TemplateTable::fast_xaccess(TosState state) { + transition(vtos, state); + + // get receiver + __ movptr(rax, aaddress(0)); + // access constant pool cache + __ get_cache_and_index_at_bcp(rcx, rdx, 2); + __ movptr(rbx, + Address(rcx, rdx, Address::times_ptr, + in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()))); + // make sure exception is reported in correct bcp range (getfield is + // next instruction) + __ increment(rbcp); + __ null_check(rax); + const Address field = Address(rax, rbx, Address::times_1, 0*wordSize); + switch (state) { + case itos: + __ movl(rax, field); + break; + case atos: + __ load_heap_oop(rax, field); + __ verify_oop(rax); + break; + case ftos: + LP64_ONLY(__ movflt(xmm0, field)); + NOT_LP64(__ fld_s(field)); + break; + default: + ShouldNotReachHere(); + } + + // [jk] not needed currently + // if (os::is_MP()) { + // Label notVolatile; + // __ movl(rdx, Address(rcx, rdx, Address::times_8, + // in_bytes(ConstantPoolCache::base_offset() + + // ConstantPoolCacheEntry::flags_offset()))); + // __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); + // __ testl(rdx, 0x1); + // __ jcc(Assembler::zero, notVolatile); + // __ membar(Assembler::LoadLoad); + // __ bind(notVolatile); + // } + + __ decrement(rbcp); +} + +//----------------------------------------------------------------------------- +// Calls + +void TemplateTable::count_calls(Register method, Register temp) { + // implemented elsewhere + ShouldNotReachHere(); +} + +void TemplateTable::prepare_invoke(int byte_no, + Register method, // linked method (or i-klass) + Register index, // itable index, MethodType, etc. + Register recv, // if caller wants to see it + Register flags // if caller wants to test it + ) { + // determine flags + const Bytecodes::Code code = bytecode(); + const bool is_invokeinterface = code == Bytecodes::_invokeinterface; + const bool is_invokedynamic = code == Bytecodes::_invokedynamic; + const bool is_invokehandle = code == Bytecodes::_invokehandle; + const bool is_invokevirtual = code == Bytecodes::_invokevirtual; + const bool is_invokespecial = code == Bytecodes::_invokespecial; + const bool load_receiver = (recv != noreg); + const bool save_flags = (flags != noreg); + assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); + assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); + assert(flags == noreg || flags == rdx, ""); + assert(recv == noreg || recv == rcx, ""); + + // setup registers & access constant pool cache + if (recv == noreg) recv = rcx; + if (flags == noreg) flags = rdx; + assert_different_registers(method, index, recv, flags); + + // save 'interpreter return address' + __ save_bcp(); + + load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); + + // maybe push appendix to arguments (just before return address) + if (is_invokedynamic || is_invokehandle) { + Label L_no_push; + __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift)); + __ jcc(Assembler::zero, L_no_push); + // Push the appendix as a trailing parameter. + // This must be done before we get the receiver, + // since the parameter_size includes it. + __ push(rbx); + __ mov(rbx, index); + assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); + __ load_resolved_reference_at_index(index, rbx); + __ pop(rbx); + __ push(index); // push appendix (MethodType, CallSite, etc.) + __ bind(L_no_push); + } + + // load receiver if needed (after appendix is pushed so parameter size is correct) + // Note: no return address pushed yet + if (load_receiver) { + __ movl(recv, flags); + __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask); + const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address + const int receiver_is_at_end = -1; // back off one slot to get receiver + Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end); + __ movptr(recv, recv_addr); + __ verify_oop(recv); + } + + if (save_flags) { + __ movl(rbcp, flags); + } + + // compute return type + __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); + // Make sure we don't need to mask flags after the above shift + ConstantPoolCacheEntry::verify_tos_state_shift(); + // load return address + { + const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); + ExternalAddress table(table_addr); + LP64_ONLY(__ lea(rscratch1, table)); + LP64_ONLY(__ movptr(flags, Address(rscratch1, flags, Address::times_ptr))); + NOT_LP64(__ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)))); + } + + // push return address + __ push(flags); + + // Restore flags value from the constant pool cache, and restore rsi + // for later null checks. r13 is the bytecode pointer + if (save_flags) { + __ movl(flags, rbcp); + __ restore_bcp(); + } +} + +void TemplateTable::invokevirtual_helper(Register index, + Register recv, + Register flags) { + // Uses temporary registers rax, rdx + assert_different_registers(index, recv, rax, rdx); + assert(index == rbx, ""); + assert(recv == rcx, ""); + + // Test for an invoke of a final method + Label notFinal; + __ movl(rax, flags); + __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); + __ jcc(Assembler::zero, notFinal); + + const Register method = index; // method must be rbx + assert(method == rbx, + "Method* must be rbx for interpreter calling convention"); + + // do the call - the index is actually the method to call + // that is, f2 is a vtable index if !is_vfinal, else f2 is a Method* + + // It's final, need a null check here! + __ null_check(recv); + + // profile this call + __ profile_final_call(rax); + __ profile_arguments_type(rax, method, rbcp, true); + + __ jump_from_interpreted(method, rax); + + __ bind(notFinal); + + // get receiver klass + __ null_check(recv, oopDesc::klass_offset_in_bytes()); + __ load_klass(rax, recv); + + // profile this call + __ profile_virtual_call(rax, rlocals, rdx); + // get target Method* & entry point + __ lookup_virtual_method(rax, index, method); + __ profile_arguments_type(rdx, method, rbcp, true); + __ jump_from_interpreted(method, rdx); +} + +void TemplateTable::invokevirtual(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f2_byte, "use this argument"); + prepare_invoke(byte_no, + rbx, // method or vtable index + noreg, // unused itable index + rcx, rdx); // recv, flags + + // rbx: index + // rcx: receiver + // rdx: flags + + invokevirtual_helper(rbx, rcx, rdx); +} + +void TemplateTable::invokespecial(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + prepare_invoke(byte_no, rbx, noreg, // get f1 Method* + rcx); // get receiver also for null check + __ verify_oop(rcx); + __ null_check(rcx); + // do the call + __ profile_call(rax); + __ profile_arguments_type(rax, rbx, rbcp, false); + __ jump_from_interpreted(rbx, rax); +} + +void TemplateTable::invokestatic(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + prepare_invoke(byte_no, rbx); // get f1 Method* + // do the call + __ profile_call(rax); + __ profile_arguments_type(rax, rbx, rbcp, false); + __ jump_from_interpreted(rbx, rax); +} + + +void TemplateTable::fast_invokevfinal(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f2_byte, "use this argument"); + __ stop("fast_invokevfinal not used on x86"); +} + + +void TemplateTable::invokeinterface(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index + rcx, rdx); // recv, flags + + // rax: interface klass (from f1) + // rbx: itable index (from f2) + // rcx: receiver + // rdx: flags + + // Special case of invokeinterface called for virtual method of + // java.lang.Object. See cpCacheOop.cpp for details. + // This code isn't produced by javac, but could be produced by + // another compliant java compiler. + Label notMethod; + __ movl(rlocals, rdx); + __ andl(rlocals, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); + + __ jcc(Assembler::zero, notMethod); + + invokevirtual_helper(rbx, rcx, rdx); + __ bind(notMethod); + + // Get receiver klass into rdx - also a null check + __ restore_locals(); // restore r14 + __ null_check(rcx, oopDesc::klass_offset_in_bytes()); + __ load_klass(rdx, rcx); + + // profile this call + __ profile_virtual_call(rdx, rbcp, rlocals); + + Label no_such_interface, no_such_method; + + __ lookup_interface_method(// inputs: rec. class, interface, itable index + rdx, rax, rbx, + // outputs: method, scan temp. reg + rbx, rbcp, + no_such_interface); + + // rbx: Method* to call + // rcx: receiver + // Check for abstract method error + // Note: This should be done more efficiently via a throw_abstract_method_error + // interpreter entry point and a conditional jump to it in case of a null + // method. + __ testptr(rbx, rbx); + __ jcc(Assembler::zero, no_such_method); + + __ profile_arguments_type(rdx, rbx, rbcp, true); + + // do the call + // rcx: receiver + // rbx,: Method* + __ jump_from_interpreted(rbx, rdx); + __ should_not_reach_here(); + + // exception handling code follows... + // note: must restore interpreter registers to canonical + // state for exception handling to work correctly! + + __ bind(no_such_method); + // throw exception + __ pop(rbx); // pop return address (pushed by prepare_invoke) + __ restore_bcp(); // rbcp must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + + __ bind(no_such_interface); + // throw exception + __ pop(rbx); // pop return address (pushed by prepare_invoke) + __ restore_bcp(); // rbcp must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_IncompatibleClassChangeError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); +} + +void TemplateTable::invokehandle(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + const Register rbx_method = rbx; + const Register rax_mtype = rax; + const Register rcx_recv = rcx; + const Register rdx_flags = rdx; + + prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv); + __ verify_method_ptr(rbx_method); + __ verify_oop(rcx_recv); + __ null_check(rcx_recv); + + // rax: MethodType object (from cpool->resolved_references[f1], if necessary) + // rbx: MH.invokeExact_MT method (from f2) + + // Note: rax_mtype is already pushed (if necessary) by prepare_invoke + + // FIXME: profile the LambdaForm also + __ profile_final_call(rax); + __ profile_arguments_type(rdx, rbx_method, rbcp, true); + + __ jump_from_interpreted(rbx_method, rdx); +} + +void TemplateTable::invokedynamic(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); + + const Register rbx_method = rbx; + const Register rax_callsite = rax; + + prepare_invoke(byte_no, rbx_method, rax_callsite); + + // rax: CallSite object (from cpool->resolved_references[f1]) + // rbx: MH.linkToCallSite method (from f2) + + // Note: rax_callsite is already pushed by prepare_invoke + + // %%% should make a type profile for any invokedynamic that takes a ref argument + // profile this call + __ profile_call(rbcp); + __ profile_arguments_type(rdx, rbx_method, rbcp, false); + + __ verify_oop(rax_callsite); + + __ jump_from_interpreted(rbx_method, rdx); +} + +//----------------------------------------------------------------------------- +// Allocation + +void TemplateTable::_new() { + transition(vtos, atos); + __ get_unsigned_2_byte_index_at_bcp(rdx, 1); + Label slow_case; + Label slow_case_no_pop; + Label done; + Label initialize_header; + Label initialize_object; // including clearing the fields + Label allocate_shared; + + __ get_cpool_and_tags(rcx, rax); + + // Make sure the class we're about to instantiate has been resolved. + // This is done before loading InstanceKlass to be consistent with the order + // how Constant Pool is updated (see ConstantPool::klass_at_put) + const int tags_offset = Array::base_offset_in_bytes(); + __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), JVM_CONSTANT_Class); + __ jcc(Assembler::notEqual, slow_case_no_pop); + + // get InstanceKlass + __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool))); + __ push(rcx); // save the contexts of klass for initializing the header + + // make sure klass is initialized & doesn't have finalizer + // make sure klass is fully initialized + __ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized); + __ jcc(Assembler::notEqual, slow_case); + + // get instance_size in InstanceKlass (scaled to a count of bytes) + __ movl(rdx, Address(rcx, Klass::layout_helper_offset())); + // test to see if it has a finalizer or is malformed in some way + __ testl(rdx, Klass::_lh_instance_slow_path_bit); + __ jcc(Assembler::notZero, slow_case); + + // + // Allocate the instance + // 1) Try to allocate in the TLAB + // 2) if fail and the object is large allocate in the shared Eden + // 3) if the above fails (or is not applicable), go to a slow case + // (creates a new TLAB, etc.) + + const bool allow_shared_alloc = + Universe::heap()->supports_inline_contig_alloc(); + + const Register thread = LP64_ONLY(r15_thread) NOT_LP64(rcx); +#ifndef _LP64 + if (UseTLAB || allow_shared_alloc) { + __ get_thread(thread); + } +#endif // _LP64 + + if (UseTLAB) { + __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset()))); + __ lea(rbx, Address(rax, rdx, Address::times_1)); + __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset()))); + __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case); + __ movptr(Address(thread, in_bytes(JavaThread::tlab_top_offset())), rbx); + if (ZeroTLAB) { + // the fields have been already cleared + __ jmp(initialize_header); + } else { + // initialize both the header and fields + __ jmp(initialize_object); + } + } + + // Allocation in the shared Eden, if allowed. + // + // rdx: instance size in bytes + if (allow_shared_alloc) { + __ bind(allocate_shared); + + ExternalAddress heap_top((address)Universe::heap()->top_addr()); + ExternalAddress heap_end((address)Universe::heap()->end_addr()); + + Label retry; + __ bind(retry); + __ movptr(rax, heap_top); + __ lea(rbx, Address(rax, rdx, Address::times_1)); + __ cmpptr(rbx, heap_end); + __ jcc(Assembler::above, slow_case); + + // Compare rax, with the top addr, and if still equal, store the new + // top addr in rbx, at the address of the top addr pointer. Sets ZF if was + // equal, and clears it otherwise. Use lock prefix for atomicity on MPs. + // + // rax,: object begin + // rbx,: object end + // rdx: instance size in bytes + __ locked_cmpxchgptr(rbx, heap_top); + + // if someone beat us on the allocation, try again, otherwise continue + __ jcc(Assembler::notEqual, retry); + + __ incr_allocated_bytes(thread, rdx, 0); + } + + if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { + // The object is initialized before the header. If the object size is + // zero, go directly to the header initialization. + __ bind(initialize_object); + __ decrement(rdx, sizeof(oopDesc)); + __ jcc(Assembler::zero, initialize_header); + + // Initialize topmost object field, divide rdx by 8, check if odd and + // test if zero. + __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) + __ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd + + // rdx must have been multiple of 8 +#ifdef ASSERT + // make sure rdx was multiple of 8 + Label L; + // Ignore partial flag stall after shrl() since it is debug VM + __ jccb(Assembler::carryClear, L); + __ stop("object size is not multiple of 2 - adjust this code"); + __ bind(L); + // rdx must be > 0, no extra check needed here +#endif + + // initialize remaining object fields: rdx was a multiple of 8 + { Label loop; + __ bind(loop); + __ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 1*oopSize), rcx); + NOT_LP64(__ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 2*oopSize), rcx)); + __ decrement(rdx); + __ jcc(Assembler::notZero, loop); + } + + // initialize object header only. + __ bind(initialize_header); + if (UseBiasedLocking) { + __ pop(rcx); // get saved klass back in the register. + __ movptr(rbx, Address(rcx, Klass::prototype_header_offset())); + __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), rbx); + } else { + __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), + (intptr_t)markOopDesc::prototype()); // header + __ pop(rcx); // get saved klass back in the register. + } +#ifdef _LP64 + __ xorl(rsi, rsi); // use zero reg to clear memory (shorter code) + __ store_klass_gap(rax, rsi); // zero klass gap for compressed oops +#endif + __ store_klass(rax, rcx); // klass + + { + SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0); + // Trigger dtrace event for fastpath + __ push(atos); + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); + __ pop(atos); + } + + __ jmp(done); + } + + // slow case + __ bind(slow_case); + __ pop(rcx); // restore stack pointer to what it was when we came in. + __ bind(slow_case_no_pop); + + Register rarg1 = LP64_ONLY(c_rarg1) NOT_LP64(rax); + Register rarg2 = LP64_ONLY(c_rarg2) NOT_LP64(rdx); + + __ get_constant_pool(rarg1); + __ get_unsigned_2_byte_index_at_bcp(rarg2, 1); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), rarg1, rarg2); + __ verify_oop(rax); + + // continue + __ bind(done); +} + +void TemplateTable::newarray() { + transition(itos, atos); + Register rarg1 = LP64_ONLY(c_rarg1) NOT_LP64(rdx); + __ load_unsigned_byte(rarg1, at_bcp(1)); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), + rarg1, rax); +} + +void TemplateTable::anewarray() { + transition(itos, atos); + + Register rarg1 = LP64_ONLY(c_rarg1) NOT_LP64(rcx); + Register rarg2 = LP64_ONLY(c_rarg2) NOT_LP64(rdx); + + __ get_unsigned_2_byte_index_at_bcp(rarg2, 1); + __ get_constant_pool(rarg1); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), + rarg1, rarg2, rax); +} + +void TemplateTable::arraylength() { + transition(atos, itos); + __ null_check(rax, arrayOopDesc::length_offset_in_bytes()); + __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes())); +} + +void TemplateTable::checkcast() { + transition(atos, atos); + Label done, is_null, ok_is_subtype, quicked, resolved; + __ testptr(rax, rax); // object is in rax + __ jcc(Assembler::zero, is_null); + + // Get cpool & tags index + __ get_cpool_and_tags(rcx, rdx); // rcx=cpool, rdx=tags array + __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // rbx=index + // See if bytecode has already been quicked + __ cmpb(Address(rdx, rbx, + Address::times_1, + Array::base_offset_in_bytes()), + JVM_CONSTANT_Class); + __ jcc(Assembler::equal, quicked); + __ push(atos); // save receiver for result, and for GC + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); + + // vm_result_2 has metadata result +#ifndef _LP64 + // borrow rdi from locals + __ get_thread(rdi); + __ get_vm_result_2(rax, rdi); + __ restore_locals(); +#else + __ get_vm_result_2(rax, r15_thread); +#endif + + __ pop_ptr(rdx); // restore receiver + __ jmpb(resolved); + + // Get superklass in rax and subklass in rbx + __ bind(quicked); + __ mov(rdx, rax); // Save object in rdx; rax needed for subtype check + __ movptr(rax, Address(rcx, rbx, + Address::times_ptr, sizeof(ConstantPool))); + + __ bind(resolved); + __ load_klass(rbx, rdx); + + // Generate subtype check. Blows rcx, rdi. Object in rdx. + // Superklass in rax. Subklass in rbx. + __ gen_subtype_check(rbx, ok_is_subtype); + + // Come here on failure + __ push_ptr(rdx); + // object is at TOS + __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); + + // Come here on success + __ bind(ok_is_subtype); + __ mov(rax, rdx); // Restore object in rdx + + // Collect counts on whether this check-cast sees NULLs a lot or not. + if (ProfileInterpreter) { + __ jmp(done); + __ bind(is_null); + __ profile_null_seen(rcx); + } else { + __ bind(is_null); // same as 'done' + } + __ bind(done); +} + +void TemplateTable::instanceof() { + transition(atos, itos); + Label done, is_null, ok_is_subtype, quicked, resolved; + __ testptr(rax, rax); + __ jcc(Assembler::zero, is_null); + + // Get cpool & tags index + __ get_cpool_and_tags(rcx, rdx); // rcx=cpool, rdx=tags array + __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // rbx=index + // See if bytecode has already been quicked + __ cmpb(Address(rdx, rbx, + Address::times_1, + Array::base_offset_in_bytes()), + JVM_CONSTANT_Class); + __ jcc(Assembler::equal, quicked); + + __ push(atos); // save receiver for result, and for GC + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); + // vm_result_2 has metadata result + +#ifndef _LP64 + // borrow rdi from locals + __ get_thread(rdi); + __ get_vm_result_2(rax, rdi); + __ restore_locals(); +#else + __ get_vm_result_2(rax, r15_thread); +#endif + + __ pop_ptr(rdx); // restore receiver + __ verify_oop(rdx); + __ load_klass(rdx, rdx); + __ jmpb(resolved); + + // Get superklass in rax and subklass in rdx + __ bind(quicked); + __ load_klass(rdx, rax); + __ movptr(rax, Address(rcx, rbx, + Address::times_ptr, sizeof(ConstantPool))); + + __ bind(resolved); + + // Generate subtype check. Blows rcx, rdi + // Superklass in rax. Subklass in rdx. + __ gen_subtype_check(rdx, ok_is_subtype); + + // Come here on failure + __ xorl(rax, rax); + __ jmpb(done); + // Come here on success + __ bind(ok_is_subtype); + __ movl(rax, 1); + + // Collect counts on whether this test sees NULLs a lot or not. + if (ProfileInterpreter) { + __ jmp(done); + __ bind(is_null); + __ profile_null_seen(rcx); + } else { + __ bind(is_null); // same as 'done' + } + __ bind(done); + // rax = 0: obj == NULL or obj is not an instanceof the specified klass + // rax = 1: obj != NULL and obj is an instanceof the specified klass +} + + +//---------------------------------------------------------------------------------------------------- +// Breakpoints +void TemplateTable::_breakpoint() { + // Note: We get here even if we are single stepping.. + // jbug insists on setting breakpoints at every bytecode + // even if we are in single step mode. + + transition(vtos, vtos); + + Register rarg = LP64_ONLY(c_rarg1) NOT_LP64(rcx); + + // get the unpatched byte code + __ get_method(rarg); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::get_original_bytecode_at), + rarg, rbcp); + __ mov(rbx, rax); // why? + + // post the breakpoint event + __ get_method(rarg); + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), + rarg, rbcp); + + // complete the execution of original bytecode + __ dispatch_only_normal(vtos); +} + +//----------------------------------------------------------------------------- +// Exceptions + +void TemplateTable::athrow() { + transition(atos, vtos); + __ null_check(rax); + __ jump(ExternalAddress(Interpreter::throw_exception_entry())); +} + +//----------------------------------------------------------------------------- +// Synchronization +// +// Note: monitorenter & exit are symmetric routines; which is reflected +// in the assembly code structure as well +// +// Stack layout: +// +// [expressions ] <--- rsp = expression stack top +// .. +// [expressions ] +// [monitor entry] <--- monitor block top = expression stack bot +// .. +// [monitor entry] +// [frame data ] <--- monitor block bot +// ... +// [saved rbp ] <--- rbp +void TemplateTable::monitorenter() { + transition(atos, vtos); + + // check for NULL object + __ null_check(rax); + + const Address monitor_block_top( + rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + const Address monitor_block_bot( + rbp, frame::interpreter_frame_initial_sp_offset * wordSize); + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + + Label allocated; + + Register rtop = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx); + Register rmon = LP64_ONLY(c_rarg1) NOT_LP64(rdx); + + // initialize entry pointer + __ xorl(rmon, rmon); // points to free slot or NULL + + // find a free slot in the monitor block (result in rmon) + { + Label entry, loop, exit; + __ movptr(rtop, monitor_block_top); // points to current entry, + // starting with top-most entry + __ lea(rbot, monitor_block_bot); // points to word before bottom + // of monitor block + __ jmpb(entry); + + __ bind(loop); + // check if current entry is used + __ cmpptr(Address(rtop, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD); + // if not used then remember entry in rmon + __ cmovptr(Assembler::equal, rmon, rtop); // cmov => cmovptr + // check if current entry is for same object + __ cmpptr(rax, Address(rtop, BasicObjectLock::obj_offset_in_bytes())); + // if same object then stop searching + __ jccb(Assembler::equal, exit); + // otherwise advance to next entry + __ addptr(rtop, entry_size); + __ bind(entry); + // check if bottom reached + __ cmpptr(rtop, rbot); + // if not at bottom then check this entry + __ jcc(Assembler::notEqual, loop); + __ bind(exit); + } + + __ testptr(rmon, rmon); // check if a slot has been found + __ jcc(Assembler::notZero, allocated); // if found, continue with that one + + // allocate one if there's no free slot + { + Label entry, loop; + // 1. compute new pointers // rsp: old expression stack top + __ movptr(rmon, monitor_block_bot); // rmon: old expression stack bottom + __ subptr(rsp, entry_size); // move expression stack top + __ subptr(rmon, entry_size); // move expression stack bottom + __ mov(rtop, rsp); // set start value for copy loop + __ movptr(monitor_block_bot, rmon); // set new monitor block bottom + __ jmp(entry); + // 2. move expression stack contents + __ bind(loop); + __ movptr(rbot, Address(rtop, entry_size)); // load expression stack + // word from old location + __ movptr(Address(rtop, 0), rbot); // and store it at new location + __ addptr(rtop, wordSize); // advance to next word + __ bind(entry); + __ cmpptr(rtop, rmon); // check if bottom reached + __ jcc(Assembler::notEqual, loop); // if not at bottom then + // copy next word + } + + // call run-time routine + // rmon: points to monitor entry + __ bind(allocated); + + // Increment bcp to point to the next bytecode, so exception + // handling for async. exceptions work correctly. + // The object has already been poped from the stack, so the + // expression stack looks correct. + __ increment(rbcp); + + // store object + __ movptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), rax); + __ lock_object(rmon); + + // check to make sure this monitor doesn't cause stack overflow after locking + __ save_bcp(); // in case of exception + __ generate_stack_overflow_check(0); + + // The bcp has already been incremented. Just need to dispatch to + // next instruction. + __ dispatch_next(vtos); +} + +void TemplateTable::monitorexit() { + transition(atos, vtos); + + // check for NULL object + __ null_check(rax); + + const Address monitor_block_top( + rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); + const Address monitor_block_bot( + rbp, frame::interpreter_frame_initial_sp_offset * wordSize); + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + + Register rtop = LP64_ONLY(c_rarg1) NOT_LP64(rdx); + Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx); + + Label found; + + // find matching slot + { + Label entry, loop; + __ movptr(rtop, monitor_block_top); // points to current entry, + // starting with top-most entry + __ lea(rbot, monitor_block_bot); // points to word before bottom + // of monitor block + __ jmpb(entry); + + __ bind(loop); + // check if current entry is for same object + __ cmpptr(rax, Address(rtop, BasicObjectLock::obj_offset_in_bytes())); + // if same object then stop searching + __ jcc(Assembler::equal, found); + // otherwise advance to next entry + __ addptr(rtop, entry_size); + __ bind(entry); + // check if bottom reached + __ cmpptr(rtop, rbot); + // if not at bottom then check this entry + __ jcc(Assembler::notEqual, loop); + } + + // error handling. Unlocking was not block-structured + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_illegal_monitor_state_exception)); + __ should_not_reach_here(); + + // call run-time routine + __ bind(found); + __ push_ptr(rax); // make sure object is on stack (contract with oopMaps) + __ unlock_object(rtop); + __ pop_ptr(rax); // discard object +} + +// Wide instructions +void TemplateTable::wide() { + transition(vtos, vtos); + __ load_unsigned_byte(rbx, at_bcp(1)); + ExternalAddress wtable((address)Interpreter::_wentry_point); + __ jump(ArrayAddress(wtable, Address(noreg, rbx, Address::times_ptr))); + // Note: the rbcp increment step is part of the individual wide bytecode implementations +} + +// Multi arrays +void TemplateTable::multianewarray() { + transition(vtos, atos); + + Register rarg = LP64_ONLY(c_rarg1) NOT_LP64(rax); + __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions + // last dim is on top of stack; we want address of first one: + // first_addr = last_addr + (ndims - 1) * stackElementSize - 1*wordsize + // the latter wordSize to point to the beginning of the array. + __ lea(rarg, Address(rsp, rax, Interpreter::stackElementScale(), -wordSize)); + call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), rarg); + __ load_unsigned_byte(rbx, at_bcp(3)); + __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); // get rid of counts +} +#endif /* !CC_INTERP */ + diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3668 +0,0 @@ -/* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" -#include "interpreter/interp_masm.hpp" -#include "interpreter/templateTable.hpp" -#include "memory/universe.inline.hpp" -#include "oops/methodData.hpp" -#include "oops/objArrayKlass.hpp" -#include "oops/oop.inline.hpp" -#include "prims/methodHandles.hpp" -#include "runtime/sharedRuntime.hpp" -#include "runtime/stubRoutines.hpp" -#include "runtime/synchronizer.hpp" -#include "utilities/macros.hpp" - -#ifndef CC_INTERP -#define __ _masm-> - -//---------------------------------------------------------------------------------------------------- -// Platform-dependent initialization - -void TemplateTable::pd_initialize() { - // No i486 specific initialization -} - -//---------------------------------------------------------------------------------------------------- -// Address computation - -// local variables -static inline Address iaddress(int n) { - return Address(rdi, Interpreter::local_offset_in_bytes(n)); -} - -static inline Address laddress(int n) { return iaddress(n + 1); } -static inline Address haddress(int n) { return iaddress(n + 0); } -static inline Address faddress(int n) { return iaddress(n); } -static inline Address daddress(int n) { return laddress(n); } -static inline Address aaddress(int n) { return iaddress(n); } - -static inline Address iaddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale()); -} -static inline Address laddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(1)); -} -static inline Address haddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(0)); -} - -static inline Address faddress(Register r) { return iaddress(r); } -static inline Address daddress(Register r) { return laddress(r); } -static inline Address aaddress(Register r) { return iaddress(r); } - -// expression stack -// (Note: Must not use symmetric equivalents at_rsp_m1/2 since they store -// data beyond the rsp which is potentially unsafe in an MT environment; -// an interrupt may overwrite that data.) -static inline Address at_rsp () { - return Address(rsp, 0); -} - -// At top of Java expression stack which may be different than rsp(). It -// isn't for category 1 objects. -static inline Address at_tos () { - Address tos = Address(rsp, Interpreter::expr_offset_in_bytes(0)); - return tos; -} - -static inline Address at_tos_p1() { - return Address(rsp, Interpreter::expr_offset_in_bytes(1)); -} - -static inline Address at_tos_p2() { - return Address(rsp, Interpreter::expr_offset_in_bytes(2)); -} - -// Condition conversion -static Assembler::Condition j_not(TemplateTable::Condition cc) { - switch (cc) { - case TemplateTable::equal : return Assembler::notEqual; - case TemplateTable::not_equal : return Assembler::equal; - case TemplateTable::less : return Assembler::greaterEqual; - case TemplateTable::less_equal : return Assembler::greater; - case TemplateTable::greater : return Assembler::lessEqual; - case TemplateTable::greater_equal: return Assembler::less; - } - ShouldNotReachHere(); - return Assembler::zero; -} - - -//---------------------------------------------------------------------------------------------------- -// Miscelaneous helper routines - -// Store an oop (or NULL) at the address described by obj. -// If val == noreg this means store a NULL - -static void do_oop_store(InterpreterMacroAssembler* _masm, - Address obj, - Register val, - BarrierSet::Name barrier, - bool precise) { - assert(val == noreg || val == rax, "parameter is just for looks"); - switch (barrier) { -#if INCLUDE_ALL_GCS - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging: - { - // flatten object address if needed - // We do it regardless of precise because we need the registers - if (obj.index() == noreg && obj.disp() == 0) { - if (obj.base() != rdx) { - __ movl(rdx, obj.base()); - } - } else { - __ leal(rdx, obj); - } - __ get_thread(rcx); - __ save_bcp(); - __ g1_write_barrier_pre(rdx /* obj */, - rbx /* pre_val */, - rcx /* thread */, - rsi /* tmp */, - val != noreg /* tosca_live */, - false /* expand_call */); - - // Do the actual store - // noreg means NULL - if (val == noreg) { - __ movptr(Address(rdx, 0), NULL_WORD); - // No post barrier for NULL - } else { - __ movl(Address(rdx, 0), val); - __ g1_write_barrier_post(rdx /* store_adr */, - val /* new_val */, - rcx /* thread */, - rbx /* tmp */, - rsi /* tmp2 */); - } - __ restore_bcp(); - - } - break; -#endif // INCLUDE_ALL_GCS - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: - { - if (val == noreg) { - __ movptr(obj, NULL_WORD); - } else { - __ movl(obj, val); - // flatten object address if needed - if (!precise || (obj.index() == noreg && obj.disp() == 0)) { - __ store_check(obj.base()); - } else { - __ leal(rdx, obj); - __ store_check(rdx); - } - } - } - break; - case BarrierSet::ModRef: - if (val == noreg) { - __ movptr(obj, NULL_WORD); - } else { - __ movl(obj, val); - } - break; - default : - ShouldNotReachHere(); - - } -} - -Address TemplateTable::at_bcp(int offset) { - assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); - return Address(rsi, offset); -} - - -void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, - Register temp_reg, bool load_bc_into_bc_reg/*=true*/, - int byte_no) { - if (!RewriteBytecodes) return; - Label L_patch_done; - - switch (bc) { - case Bytecodes::_fast_aputfield: - case Bytecodes::_fast_bputfield: - case Bytecodes::_fast_cputfield: - case Bytecodes::_fast_dputfield: - case Bytecodes::_fast_fputfield: - case Bytecodes::_fast_iputfield: - case Bytecodes::_fast_lputfield: - case Bytecodes::_fast_sputfield: - { - // We skip bytecode quickening for putfield instructions when - // the put_code written to the constant pool cache is zero. - // This is required so that every execution of this instruction - // calls out to InterpreterRuntime::resolve_get_put to do - // additional, required work. - assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - assert(load_bc_into_bc_reg, "we use bc_reg as temp"); - __ get_cache_and_index_and_bytecode_at_bcp(bc_reg, temp_reg, temp_reg, byte_no, 1); - __ movl(bc_reg, bc); - __ cmpl(temp_reg, (int) 0); - __ jcc(Assembler::zero, L_patch_done); // don't patch - } - break; - default: - assert(byte_no == -1, "sanity"); - // the pair bytecodes have already done the load. - if (load_bc_into_bc_reg) { - __ movl(bc_reg, bc); - } - } - - if (JvmtiExport::can_post_breakpoint()) { - Label L_fast_patch; - // if a breakpoint is present we can't rewrite the stream directly - __ movzbl(temp_reg, at_bcp(0)); - __ cmpl(temp_reg, Bytecodes::_breakpoint); - __ jcc(Assembler::notEqual, L_fast_patch); - __ get_method(temp_reg); - // Let breakpoint table handling rewrite to quicker bytecode - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, rsi, bc_reg); -#ifndef ASSERT - __ jmpb(L_patch_done); -#else - __ jmp(L_patch_done); -#endif - __ bind(L_fast_patch); - } - -#ifdef ASSERT - Label L_okay; - __ load_unsigned_byte(temp_reg, at_bcp(0)); - __ cmpl(temp_reg, (int)Bytecodes::java_code(bc)); - __ jccb(Assembler::equal, L_okay); - __ cmpl(temp_reg, bc_reg); - __ jcc(Assembler::equal, L_okay); - __ stop("patching the wrong bytecode"); - __ bind(L_okay); -#endif - - // patch bytecode - __ movb(at_bcp(0), bc_reg); - __ bind(L_patch_done); -} - -//---------------------------------------------------------------------------------------------------- -// Individual instructions - -void TemplateTable::nop() { - transition(vtos, vtos); - // nothing to do -} - -void TemplateTable::shouldnotreachhere() { - transition(vtos, vtos); - __ stop("shouldnotreachhere bytecode"); -} - - - -void TemplateTable::aconst_null() { - transition(vtos, atos); - __ xorptr(rax, rax); -} - - -void TemplateTable::iconst(int value) { - transition(vtos, itos); - if (value == 0) { - __ xorptr(rax, rax); - } else { - __ movptr(rax, value); - } -} - - -void TemplateTable::lconst(int value) { - transition(vtos, ltos); - if (value == 0) { - __ xorptr(rax, rax); - } else { - __ movptr(rax, value); - } - assert(value >= 0, "check this code"); - __ xorptr(rdx, rdx); -} - - -void TemplateTable::fconst(int value) { - transition(vtos, ftos); - if (value == 0) { __ fldz(); - } else if (value == 1) { __ fld1(); - } else if (value == 2) { __ fld1(); __ fld1(); __ faddp(); // should do a better solution here - } else { ShouldNotReachHere(); - } -} - - -void TemplateTable::dconst(int value) { - transition(vtos, dtos); - if (value == 0) { __ fldz(); - } else if (value == 1) { __ fld1(); - } else { ShouldNotReachHere(); - } -} - - -void TemplateTable::bipush() { - transition(vtos, itos); - __ load_signed_byte(rax, at_bcp(1)); -} - - -void TemplateTable::sipush() { - transition(vtos, itos); - __ load_unsigned_short(rax, at_bcp(1)); - __ bswapl(rax); - __ sarl(rax, 16); -} - -void TemplateTable::ldc(bool wide) { - transition(vtos, vtos); - Label call_ldc, notFloat, notClass, Done; - - if (wide) { - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); - } else { - __ load_unsigned_byte(rbx, at_bcp(1)); - } - __ get_cpool_and_tags(rcx, rax); - const int base_offset = ConstantPool::header_size() * wordSize; - const int tags_offset = Array::base_offset_in_bytes(); - - // get type - __ xorptr(rdx, rdx); - __ movb(rdx, Address(rax, rbx, Address::times_1, tags_offset)); - - // unresolved class - get the resolved class - __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass); - __ jccb(Assembler::equal, call_ldc); - - // unresolved class in error (resolution failed) - call into runtime - // so that the same error from first resolution attempt is thrown. - __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError); - __ jccb(Assembler::equal, call_ldc); - - // resolved class - need to call vm to get java mirror of the class - __ cmpl(rdx, JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, notClass); - - __ bind(call_ldc); - __ movl(rcx, wide); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), rcx); - __ push(atos); - __ jmp(Done); - - __ bind(notClass); - __ cmpl(rdx, JVM_CONSTANT_Float); - __ jccb(Assembler::notEqual, notFloat); - // ftos - __ fld_s( Address(rcx, rbx, Address::times_ptr, base_offset)); - __ push(ftos); - __ jmp(Done); - - __ bind(notFloat); -#ifdef ASSERT - { Label L; - __ cmpl(rdx, JVM_CONSTANT_Integer); - __ jcc(Assembler::equal, L); - // String and Object are rewritten to fast_aldc - __ stop("unexpected tag type in ldc"); - __ bind(L); - } -#endif - // itos JVM_CONSTANT_Integer only - __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset)); - __ push(itos); - __ bind(Done); -} - -// Fast path for caching oop constants. -void TemplateTable::fast_aldc(bool wide) { - transition(vtos, atos); - - Register result = rax; - Register tmp = rdx; - int index_size = wide ? sizeof(u2) : sizeof(u1); - - Label resolved; - - // We are resolved if the resolved reference cache entry contains a - // non-null object (String, MethodType, etc.) - assert_different_registers(result, tmp); - __ get_cache_index_at_bcp(tmp, 1, index_size); - __ load_resolved_reference_at_index(result, tmp); - __ testl(result, result); - __ jcc(Assembler::notZero, resolved); - - address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); - - // first time invocation - must resolve first - __ movl(tmp, (int)bytecode()); - __ call_VM(result, entry, tmp); - - __ bind(resolved); - - if (VerifyOops) { - __ verify_oop(result); - } -} - -void TemplateTable::ldc2_w() { - transition(vtos, vtos); - Label Long, Done; - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); - - __ get_cpool_and_tags(rcx, rax); - const int base_offset = ConstantPool::header_size() * wordSize; - const int tags_offset = Array::base_offset_in_bytes(); - - // get type - __ cmpb(Address(rax, rbx, Address::times_1, tags_offset), JVM_CONSTANT_Double); - __ jccb(Assembler::notEqual, Long); - // dtos - __ fld_d( Address(rcx, rbx, Address::times_ptr, base_offset)); - __ push(dtos); - __ jmpb(Done); - - __ bind(Long); - // ltos - __ movptr(rax, Address(rcx, rbx, Address::times_ptr, base_offset + 0 * wordSize)); - NOT_LP64(__ movptr(rdx, Address(rcx, rbx, Address::times_ptr, base_offset + 1 * wordSize))); - - __ push(ltos); - - __ bind(Done); -} - - -void TemplateTable::locals_index(Register reg, int offset) { - __ load_unsigned_byte(reg, at_bcp(offset)); - __ negptr(reg); -} - - -void TemplateTable::iload() { - transition(vtos, itos); - if (RewriteFrequentPairs) { - Label rewrite, done; - - // get next byte - __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_iload))); - // if _iload, wait to rewrite to iload2. We only want to rewrite the - // last two iloads in a pair. Comparing against fast_iload means that - // the next bytecode is neither an iload or a caload, and therefore - // an iload pair. - __ cmpl(rbx, Bytecodes::_iload); - __ jcc(Assembler::equal, done); - - __ cmpl(rbx, Bytecodes::_fast_iload); - __ movl(rcx, Bytecodes::_fast_iload2); - __ jccb(Assembler::equal, rewrite); - - // if _caload, rewrite to fast_icaload - __ cmpl(rbx, Bytecodes::_caload); - __ movl(rcx, Bytecodes::_fast_icaload); - __ jccb(Assembler::equal, rewrite); - - // rewrite so iload doesn't check again. - __ movl(rcx, Bytecodes::_fast_iload); - - // rewrite - // rcx: fast bytecode - __ bind(rewrite); - patch_bytecode(Bytecodes::_iload, rcx, rbx, false); - __ bind(done); - } - - // Get the local value into tos - locals_index(rbx); - __ movl(rax, iaddress(rbx)); -} - - -void TemplateTable::fast_iload2() { - transition(vtos, itos); - locals_index(rbx); - __ movl(rax, iaddress(rbx)); - __ push(itos); - locals_index(rbx, 3); - __ movl(rax, iaddress(rbx)); -} - -void TemplateTable::fast_iload() { - transition(vtos, itos); - locals_index(rbx); - __ movl(rax, iaddress(rbx)); -} - - -void TemplateTable::lload() { - transition(vtos, ltos); - locals_index(rbx); - __ movptr(rax, laddress(rbx)); - NOT_LP64(__ movl(rdx, haddress(rbx))); -} - - -void TemplateTable::fload() { - transition(vtos, ftos); - locals_index(rbx); - __ fld_s(faddress(rbx)); -} - - -void TemplateTable::dload() { - transition(vtos, dtos); - locals_index(rbx); - __ fld_d(daddress(rbx)); -} - - -void TemplateTable::aload() { - transition(vtos, atos); - locals_index(rbx); - __ movptr(rax, aaddress(rbx)); -} - - -void TemplateTable::locals_index_wide(Register reg) { - __ load_unsigned_short(reg, at_bcp(2)); - __ bswapl(reg); - __ shrl(reg, 16); - __ negptr(reg); -} - - -void TemplateTable::wide_iload() { - transition(vtos, itos); - locals_index_wide(rbx); - __ movl(rax, iaddress(rbx)); -} - - -void TemplateTable::wide_lload() { - transition(vtos, ltos); - locals_index_wide(rbx); - __ movptr(rax, laddress(rbx)); - NOT_LP64(__ movl(rdx, haddress(rbx))); -} - - -void TemplateTable::wide_fload() { - transition(vtos, ftos); - locals_index_wide(rbx); - __ fld_s(faddress(rbx)); -} - - -void TemplateTable::wide_dload() { - transition(vtos, dtos); - locals_index_wide(rbx); - __ fld_d(daddress(rbx)); -} - - -void TemplateTable::wide_aload() { - transition(vtos, atos); - locals_index_wide(rbx); - __ movptr(rax, aaddress(rbx)); -} - -void TemplateTable::index_check(Register array, Register index) { - // Pop ptr into array - __ pop_ptr(array); - index_check_without_pop(array, index); -} - -void TemplateTable::index_check_without_pop(Register array, Register index) { - // destroys rbx, - // check array - __ null_check(array, arrayOopDesc::length_offset_in_bytes()); - LP64_ONLY(__ movslq(index, index)); - // check index - __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes())); - if (index != rbx) { - // ??? convention: move aberrant index into rbx, for exception message - assert(rbx != array, "different registers"); - __ mov(rbx, index); - } - __ jump_cc(Assembler::aboveEqual, - ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); -} - - -void TemplateTable::iaload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ movl(rax, Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT))); -} - - -void TemplateTable::laload() { - transition(itos, ltos); - // rax,: index - // rdx: array - index_check(rdx, rax); - __ mov(rbx, rax); - // rbx,: index - __ movptr(rax, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize)); - NOT_LP64(__ movl(rdx, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize))); -} - - -void TemplateTable::faload() { - transition(itos, ftos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ fld_s(Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT))); -} - - -void TemplateTable::daload() { - transition(itos, dtos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ fld_d(Address(rdx, rax, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); -} - - -void TemplateTable::aaload() { - transition(itos, atos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - __ movptr(rax, Address(rdx, rax, Address::times_ptr, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); -} - - -void TemplateTable::baload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - // can do better code for P5 - fix this at some point - __ load_signed_byte(rbx, Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE))); - __ mov(rax, rbx); -} - - -void TemplateTable::caload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - // can do better code for P5 - may want to improve this at some point - __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - __ mov(rax, rbx); -} - -// iload followed by caload frequent pair -void TemplateTable::fast_icaload() { - transition(vtos, itos); - // load index out of locals - locals_index(rbx); - __ movl(rax, iaddress(rbx)); - - // rdx: array - index_check(rdx, rax); - // rax,: index - __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - __ mov(rax, rbx); -} - -void TemplateTable::saload() { - transition(itos, itos); - // rdx: array - index_check(rdx, rax); // kills rbx, - // rax,: index - // can do better code for P5 - may want to improve this at some point - __ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); - __ mov(rax, rbx); -} - - -void TemplateTable::iload(int n) { - transition(vtos, itos); - __ movl(rax, iaddress(n)); -} - - -void TemplateTable::lload(int n) { - transition(vtos, ltos); - __ movptr(rax, laddress(n)); - NOT_LP64(__ movptr(rdx, haddress(n))); -} - - -void TemplateTable::fload(int n) { - transition(vtos, ftos); - __ fld_s(faddress(n)); -} - - -void TemplateTable::dload(int n) { - transition(vtos, dtos); - __ fld_d(daddress(n)); -} - - -void TemplateTable::aload(int n) { - transition(vtos, atos); - __ movptr(rax, aaddress(n)); -} - - -void TemplateTable::aload_0() { - transition(vtos, atos); - // According to bytecode histograms, the pairs: - // - // _aload_0, _fast_igetfield - // _aload_0, _fast_agetfield - // _aload_0, _fast_fgetfield - // - // occur frequently. If RewriteFrequentPairs is set, the (slow) _aload_0 - // bytecode checks if the next bytecode is either _fast_igetfield, - // _fast_agetfield or _fast_fgetfield and then rewrites the - // current bytecode into a pair bytecode; otherwise it rewrites the current - // bytecode into _fast_aload_0 that doesn't do the pair check anymore. - // - // Note: If the next bytecode is _getfield, the rewrite must be delayed, - // otherwise we may miss an opportunity for a pair. - // - // Also rewrite frequent pairs - // aload_0, aload_1 - // aload_0, iload_1 - // These bytecodes with a small amount of code are most profitable to rewrite - if (RewriteFrequentPairs) { - Label rewrite, done; - // get next byte - __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); - - // do actual aload_0 - aload(0); - - // if _getfield then wait with rewrite - __ cmpl(rbx, Bytecodes::_getfield); - __ jcc(Assembler::equal, done); - - // if _igetfield then reqrite to _fast_iaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_igetfield); - __ movl(rcx, Bytecodes::_fast_iaccess_0); - __ jccb(Assembler::equal, rewrite); - - // if _agetfield then reqrite to _fast_aaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_agetfield); - __ movl(rcx, Bytecodes::_fast_aaccess_0); - __ jccb(Assembler::equal, rewrite); - - // if _fgetfield then reqrite to _fast_faccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_fgetfield); - __ movl(rcx, Bytecodes::_fast_faccess_0); - __ jccb(Assembler::equal, rewrite); - - // else rewrite to _fast_aload0 - assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "fix bytecode definition"); - __ movl(rcx, Bytecodes::_fast_aload_0); - - // rewrite - // rcx: fast bytecode - __ bind(rewrite); - patch_bytecode(Bytecodes::_aload_0, rcx, rbx, false); - - __ bind(done); - } else { - aload(0); - } -} - -void TemplateTable::istore() { - transition(itos, vtos); - locals_index(rbx); - __ movl(iaddress(rbx), rax); -} - - -void TemplateTable::lstore() { - transition(ltos, vtos); - locals_index(rbx); - __ movptr(laddress(rbx), rax); - NOT_LP64(__ movptr(haddress(rbx), rdx)); -} - - -void TemplateTable::fstore() { - transition(ftos, vtos); - locals_index(rbx); - __ fstp_s(faddress(rbx)); -} - - -void TemplateTable::dstore() { - transition(dtos, vtos); - locals_index(rbx); - __ fstp_d(daddress(rbx)); -} - - -void TemplateTable::astore() { - transition(vtos, vtos); - __ pop_ptr(rax); - locals_index(rbx); - __ movptr(aaddress(rbx), rax); -} - - -void TemplateTable::wide_istore() { - transition(vtos, vtos); - __ pop_i(rax); - locals_index_wide(rbx); - __ movl(iaddress(rbx), rax); -} - - -void TemplateTable::wide_lstore() { - transition(vtos, vtos); - __ pop_l(rax, rdx); - locals_index_wide(rbx); - __ movptr(laddress(rbx), rax); - NOT_LP64(__ movl(haddress(rbx), rdx)); -} - - -void TemplateTable::wide_fstore() { - wide_istore(); -} - - -void TemplateTable::wide_dstore() { - wide_lstore(); -} - - -void TemplateTable::wide_astore() { - transition(vtos, vtos); - __ pop_ptr(rax); - locals_index_wide(rbx); - __ movptr(aaddress(rbx), rax); -} - - -void TemplateTable::iastore() { - transition(itos, vtos); - __ pop_i(rbx); - // rax,: value - // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movl(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)), rax); -} - - -void TemplateTable::lastore() { - transition(ltos, vtos); - __ pop_i(rbx); - // rax,: low(value) - // rcx: array - // rdx: high(value) - index_check(rcx, rbx); // prefer index in rbx, - // rbx,: index - __ movptr(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize), rax); - NOT_LP64(__ movl(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize), rdx)); -} - - -void TemplateTable::fastore() { - transition(ftos, vtos); - __ pop_i(rbx); - // rdx: array - // st0: value - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ fstp_s(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT))); -} - - -void TemplateTable::dastore() { - transition(dtos, vtos); - __ pop_i(rbx); - // rdx: array - // st0: value - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ fstp_d(Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); -} - - -void TemplateTable::aastore() { - Label is_null, ok_is_subtype, done; - transition(vtos, vtos); - // stack: ..., array, index, value - __ movptr(rax, at_tos()); // Value - __ movl(rcx, at_tos_p1()); // Index - __ movptr(rdx, at_tos_p2()); // Array - - Address element_address(rdx, rcx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - index_check_without_pop(rdx, rcx); // kills rbx, - // do array store check - check for NULL value first - __ testptr(rax, rax); - __ jcc(Assembler::zero, is_null); - - // Move subklass into EBX - __ load_klass(rbx, rax); - // Move superklass into EAX - __ load_klass(rax, rdx); - __ movptr(rax, Address(rax, ObjArrayKlass::element_klass_offset())); - // Compress array+index*wordSize+12 into a single register. Frees ECX. - __ lea(rdx, element_address); - - // Generate subtype check. Blows ECX. Resets EDI to locals. - // Superklass in EAX. Subklass in EBX. - __ gen_subtype_check( rbx, ok_is_subtype ); - - // Come here on failure - // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); - - // Come here on success - __ bind(ok_is_subtype); - - // Get the value to store - __ movptr(rax, at_rsp()); - // and store it with appropriate barrier - do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true); - - __ jmp(done); - - // Have a NULL in EAX, EDX=array, ECX=index. Store NULL at ary[idx] - __ bind(is_null); - __ profile_null_seen(rbx); - - // Store NULL, (noreg means NULL to do_oop_store) - do_oop_store(_masm, element_address, noreg, _bs->kind(), true); - - // Pop stack arguments - __ bind(done); - __ addptr(rsp, 3 * Interpreter::stackElementSize); -} - - -void TemplateTable::bastore() { - transition(itos, vtos); - __ pop_i(rbx); - // rax,: value - // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), rax); -} - - -void TemplateTable::castore() { - transition(itos, vtos); - __ pop_i(rbx); - // rax,: value - // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movw(Address(rdx, rbx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), rax); -} - - -void TemplateTable::sastore() { - castore(); -} - - -void TemplateTable::istore(int n) { - transition(itos, vtos); - __ movl(iaddress(n), rax); -} - - -void TemplateTable::lstore(int n) { - transition(ltos, vtos); - __ movptr(laddress(n), rax); - NOT_LP64(__ movptr(haddress(n), rdx)); -} - - -void TemplateTable::fstore(int n) { - transition(ftos, vtos); - __ fstp_s(faddress(n)); -} - - -void TemplateTable::dstore(int n) { - transition(dtos, vtos); - __ fstp_d(daddress(n)); -} - - -void TemplateTable::astore(int n) { - transition(vtos, vtos); - __ pop_ptr(rax); - __ movptr(aaddress(n), rax); -} - - -void TemplateTable::pop() { - transition(vtos, vtos); - __ addptr(rsp, Interpreter::stackElementSize); -} - - -void TemplateTable::pop2() { - transition(vtos, vtos); - __ addptr(rsp, 2*Interpreter::stackElementSize); -} - - -void TemplateTable::dup() { - transition(vtos, vtos); - // stack: ..., a - __ load_ptr(0, rax); - __ push_ptr(rax); - // stack: ..., a, a -} - - -void TemplateTable::dup_x1() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr( 0, rax); // load b - __ load_ptr( 1, rcx); // load a - __ store_ptr(1, rax); // store b - __ store_ptr(0, rcx); // store a - __ push_ptr(rax); // push b - // stack: ..., b, a, b -} - - -void TemplateTable::dup_x2() { - transition(vtos, vtos); - // stack: ..., a, b, c - __ load_ptr( 0, rax); // load c - __ load_ptr( 2, rcx); // load a - __ store_ptr(2, rax); // store c in a - __ push_ptr(rax); // push c - // stack: ..., c, b, c, c - __ load_ptr( 2, rax); // load b - __ store_ptr(2, rcx); // store a in b - // stack: ..., c, a, c, c - __ store_ptr(1, rax); // store b in c - // stack: ..., c, a, b, c -} - - -void TemplateTable::dup2() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr(1, rax); // load a - __ push_ptr(rax); // push a - __ load_ptr(1, rax); // load b - __ push_ptr(rax); // push b - // stack: ..., a, b, a, b -} - - -void TemplateTable::dup2_x1() { - transition(vtos, vtos); - // stack: ..., a, b, c - __ load_ptr( 0, rcx); // load c - __ load_ptr( 1, rax); // load b - __ push_ptr(rax); // push b - __ push_ptr(rcx); // push c - // stack: ..., a, b, c, b, c - __ store_ptr(3, rcx); // store c in b - // stack: ..., a, c, c, b, c - __ load_ptr( 4, rcx); // load a - __ store_ptr(2, rcx); // store a in 2nd c - // stack: ..., a, c, a, b, c - __ store_ptr(4, rax); // store b in a - // stack: ..., b, c, a, b, c - // stack: ..., b, c, a, b, c -} - - -void TemplateTable::dup2_x2() { - transition(vtos, vtos); - // stack: ..., a, b, c, d - __ load_ptr( 0, rcx); // load d - __ load_ptr( 1, rax); // load c - __ push_ptr(rax); // push c - __ push_ptr(rcx); // push d - // stack: ..., a, b, c, d, c, d - __ load_ptr( 4, rax); // load b - __ store_ptr(2, rax); // store b in d - __ store_ptr(4, rcx); // store d in b - // stack: ..., a, d, c, b, c, d - __ load_ptr( 5, rcx); // load a - __ load_ptr( 3, rax); // load c - __ store_ptr(3, rcx); // store a in c - __ store_ptr(5, rax); // store c in a - // stack: ..., c, d, a, b, c, d - // stack: ..., c, d, a, b, c, d -} - - -void TemplateTable::swap() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr( 1, rcx); // load a - __ load_ptr( 0, rax); // load b - __ store_ptr(0, rcx); // store a in b - __ store_ptr(1, rax); // store b in a - // stack: ..., b, a -} - - -void TemplateTable::iop2(Operation op) { - transition(itos, itos); - switch (op) { - case add : __ pop_i(rdx); __ addl (rax, rdx); break; - case sub : __ mov(rdx, rax); __ pop_i(rax); __ subl (rax, rdx); break; - case mul : __ pop_i(rdx); __ imull(rax, rdx); break; - case _and : __ pop_i(rdx); __ andl (rax, rdx); break; - case _or : __ pop_i(rdx); __ orl (rax, rdx); break; - case _xor : __ pop_i(rdx); __ xorl (rax, rdx); break; - case shl : __ mov(rcx, rax); __ pop_i(rax); __ shll (rax); break; // implicit masking of lower 5 bits by Intel shift instr. - case shr : __ mov(rcx, rax); __ pop_i(rax); __ sarl (rax); break; // implicit masking of lower 5 bits by Intel shift instr. - case ushr : __ mov(rcx, rax); __ pop_i(rax); __ shrl (rax); break; // implicit masking of lower 5 bits by Intel shift instr. - default : ShouldNotReachHere(); - } -} - - -void TemplateTable::lop2(Operation op) { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - switch (op) { - case add : __ addl(rax, rbx); __ adcl(rdx, rcx); break; - case sub : __ subl(rbx, rax); __ sbbl(rcx, rdx); - __ mov (rax, rbx); __ mov (rdx, rcx); break; - case _and : __ andl(rax, rbx); __ andl(rdx, rcx); break; - case _or : __ orl (rax, rbx); __ orl (rdx, rcx); break; - case _xor : __ xorl(rax, rbx); __ xorl(rdx, rcx); break; - default : ShouldNotReachHere(); - } -} - - -void TemplateTable::idiv() { - transition(itos, itos); - __ mov(rcx, rax); - __ pop_i(rax); - // Note: could xor rax, and rcx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivl(rcx); -} - - -void TemplateTable::irem() { - transition(itos, itos); - __ mov(rcx, rax); - __ pop_i(rax); - // Note: could xor rax, and rcx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivl(rcx); - __ mov(rax, rdx); -} - - -void TemplateTable::lmul() { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - __ push(rcx); __ push(rbx); - __ push(rdx); __ push(rax); - __ lmul(2 * wordSize, 0); - __ addptr(rsp, 4 * wordSize); // take off temporaries -} - - -void TemplateTable::ldiv() { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - __ push(rcx); __ push(rbx); - __ push(rdx); __ push(rax); - // check if y = 0 - __ orl(rax, rdx); - __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); - __ addptr(rsp, 4 * wordSize); // take off temporaries -} - - -void TemplateTable::lrem() { - transition(ltos, ltos); - __ pop_l(rbx, rcx); - __ push(rcx); __ push(rbx); - __ push(rdx); __ push(rax); - // check if y = 0 - __ orl(rax, rdx); - __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); - __ addptr(rsp, 4 * wordSize); -} - - -void TemplateTable::lshl() { - transition(itos, ltos); - __ movl(rcx, rax); // get shift count - __ pop_l(rax, rdx); // get shift value - __ lshl(rdx, rax); -} - - -void TemplateTable::lshr() { - transition(itos, ltos); - __ mov(rcx, rax); // get shift count - __ pop_l(rax, rdx); // get shift value - __ lshr(rdx, rax, true); -} - - -void TemplateTable::lushr() { - transition(itos, ltos); - __ mov(rcx, rax); // get shift count - __ pop_l(rax, rdx); // get shift value - __ lshr(rdx, rax); -} - - -void TemplateTable::fop2(Operation op) { - transition(ftos, ftos); - switch (op) { - case add: __ fadd_s (at_rsp()); break; - case sub: __ fsubr_s(at_rsp()); break; - case mul: __ fmul_s (at_rsp()); break; - case div: __ fdivr_s(at_rsp()); break; - case rem: __ fld_s (at_rsp()); __ fremr(rax); break; - default : ShouldNotReachHere(); - } - __ f2ieee(); - __ pop(rax); // pop float thing off -} - - -void TemplateTable::dop2(Operation op) { - transition(dtos, dtos); - - switch (op) { - case add: __ fadd_d (at_rsp()); break; - case sub: __ fsubr_d(at_rsp()); break; - case mul: { - Label L_strict; - Label L_join; - const Address access_flags (rcx, Method::access_flags_offset()); - __ get_method(rcx); - __ movl(rcx, access_flags); - __ testl(rcx, JVM_ACC_STRICT); - __ jccb(Assembler::notZero, L_strict); - __ fmul_d (at_rsp()); - __ jmpb(L_join); - __ bind(L_strict); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); - __ fmulp(); - __ fmul_d (at_rsp()); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); - __ fmulp(); - __ bind(L_join); - break; - } - case div: { - Label L_strict; - Label L_join; - const Address access_flags (rcx, Method::access_flags_offset()); - __ get_method(rcx); - __ movl(rcx, access_flags); - __ testl(rcx, JVM_ACC_STRICT); - __ jccb(Assembler::notZero, L_strict); - __ fdivr_d(at_rsp()); - __ jmp(L_join); - __ bind(L_strict); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); - __ fmul_d (at_rsp()); - __ fdivrp(); - __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); - __ fmulp(); - __ bind(L_join); - break; - } - case rem: __ fld_d (at_rsp()); __ fremr(rax); break; - default : ShouldNotReachHere(); - } - __ d2ieee(); - // Pop double precision number from rsp. - __ pop(rax); - __ pop(rdx); -} - - -void TemplateTable::ineg() { - transition(itos, itos); - __ negl(rax); -} - - -void TemplateTable::lneg() { - transition(ltos, ltos); - __ lneg(rdx, rax); -} - - -void TemplateTable::fneg() { - transition(ftos, ftos); - __ fchs(); -} - - -void TemplateTable::dneg() { - transition(dtos, dtos); - __ fchs(); -} - - -void TemplateTable::iinc() { - transition(vtos, vtos); - __ load_signed_byte(rdx, at_bcp(2)); // get constant - locals_index(rbx); - __ addl(iaddress(rbx), rdx); -} - - -void TemplateTable::wide_iinc() { - transition(vtos, vtos); - __ movl(rdx, at_bcp(4)); // get constant - locals_index_wide(rbx); - __ bswapl(rdx); // swap bytes & sign-extend constant - __ sarl(rdx, 16); - __ addl(iaddress(rbx), rdx); - // Note: should probably use only one movl to get both - // the index and the constant -> fix this -} - - -void TemplateTable::convert() { - // Checking -#ifdef ASSERT - { TosState tos_in = ilgl; - TosState tos_out = ilgl; - switch (bytecode()) { - case Bytecodes::_i2l: // fall through - case Bytecodes::_i2f: // fall through - case Bytecodes::_i2d: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: tos_in = itos; break; - case Bytecodes::_l2i: // fall through - case Bytecodes::_l2f: // fall through - case Bytecodes::_l2d: tos_in = ltos; break; - case Bytecodes::_f2i: // fall through - case Bytecodes::_f2l: // fall through - case Bytecodes::_f2d: tos_in = ftos; break; - case Bytecodes::_d2i: // fall through - case Bytecodes::_d2l: // fall through - case Bytecodes::_d2f: tos_in = dtos; break; - default : ShouldNotReachHere(); - } - switch (bytecode()) { - case Bytecodes::_l2i: // fall through - case Bytecodes::_f2i: // fall through - case Bytecodes::_d2i: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: tos_out = itos; break; - case Bytecodes::_i2l: // fall through - case Bytecodes::_f2l: // fall through - case Bytecodes::_d2l: tos_out = ltos; break; - case Bytecodes::_i2f: // fall through - case Bytecodes::_l2f: // fall through - case Bytecodes::_d2f: tos_out = ftos; break; - case Bytecodes::_i2d: // fall through - case Bytecodes::_l2d: // fall through - case Bytecodes::_f2d: tos_out = dtos; break; - default : ShouldNotReachHere(); - } - transition(tos_in, tos_out); - } -#endif // ASSERT - - // Conversion - // (Note: use push(rcx)/pop(rcx) for 1/2-word stack-ptr manipulation) - switch (bytecode()) { - case Bytecodes::_i2l: - __ extend_sign(rdx, rax); - break; - case Bytecodes::_i2f: - __ push(rax); // store int on tos - __ fild_s(at_rsp()); // load int to ST0 - __ f2ieee(); // truncate to float size - __ pop(rcx); // adjust rsp - break; - case Bytecodes::_i2d: - __ push(rax); // add one slot for d2ieee() - __ push(rax); // store int on tos - __ fild_s(at_rsp()); // load int to ST0 - __ d2ieee(); // truncate to double size - __ pop(rcx); // adjust rsp - __ pop(rcx); - break; - case Bytecodes::_i2b: - __ shll(rax, 24); // truncate upper 24 bits - __ sarl(rax, 24); // and sign-extend byte - LP64_ONLY(__ movsbl(rax, rax)); - break; - case Bytecodes::_i2c: - __ andl(rax, 0xFFFF); // truncate upper 16 bits - LP64_ONLY(__ movzwl(rax, rax)); - break; - case Bytecodes::_i2s: - __ shll(rax, 16); // truncate upper 16 bits - __ sarl(rax, 16); // and sign-extend short - LP64_ONLY(__ movswl(rax, rax)); - break; - case Bytecodes::_l2i: - /* nothing to do */ - break; - case Bytecodes::_l2f: - __ push(rdx); // store long on tos - __ push(rax); - __ fild_d(at_rsp()); // load long to ST0 - __ f2ieee(); // truncate to float size - __ pop(rcx); // adjust rsp - __ pop(rcx); - break; - case Bytecodes::_l2d: - __ push(rdx); // store long on tos - __ push(rax); - __ fild_d(at_rsp()); // load long to ST0 - __ d2ieee(); // truncate to double size - __ pop(rcx); // adjust rsp - __ pop(rcx); - break; - case Bytecodes::_f2i: - __ push(rcx); // reserve space for argument - __ fstp_s(at_rsp()); // pass float argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); - break; - case Bytecodes::_f2l: - __ push(rcx); // reserve space for argument - __ fstp_s(at_rsp()); // pass float argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); - break; - case Bytecodes::_f2d: - /* nothing to do */ - break; - case Bytecodes::_d2i: - __ push(rcx); // reserve space for argument - __ push(rcx); - __ fstp_d(at_rsp()); // pass double argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 2); - break; - case Bytecodes::_d2l: - __ push(rcx); // reserve space for argument - __ push(rcx); - __ fstp_d(at_rsp()); // pass double argument on stack - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 2); - break; - case Bytecodes::_d2f: - __ push(rcx); // reserve space for f2ieee() - __ f2ieee(); // truncate to float size - __ pop(rcx); // adjust rsp - break; - default : - ShouldNotReachHere(); - } -} - - -void TemplateTable::lcmp() { - transition(ltos, itos); - // y = rdx:rax - __ pop_l(rbx, rcx); // get x = rcx:rbx - __ lcmp2int(rcx, rbx, rdx, rax);// rcx := cmp(x, y) - __ mov(rax, rcx); -} - - -void TemplateTable::float_cmp(bool is_float, int unordered_result) { - if (is_float) { - __ fld_s(at_rsp()); - } else { - __ fld_d(at_rsp()); - __ pop(rdx); - } - __ pop(rcx); - __ fcmp2int(rax, unordered_result < 0); -} - - -void TemplateTable::branch(bool is_jsr, bool is_wide) { - __ get_method(rcx); // ECX holds method - __ profile_taken_branch(rax,rbx); // EAX holds updated MDP, EBX holds bumped taken count - - const ByteSize be_offset = MethodCounters::backedge_counter_offset() + - InvocationCounter::counter_offset(); - const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + - InvocationCounter::counter_offset(); - - // Load up EDX with the branch displacement - if (is_wide) { - __ movl(rdx, at_bcp(1)); - } else { - __ load_signed_short(rdx, at_bcp(1)); - } - __ bswapl(rdx); - if (!is_wide) __ sarl(rdx, 16); - LP64_ONLY(__ movslq(rdx, rdx)); - - - // Handle all the JSR stuff here, then exit. - // It's much shorter and cleaner than intermingling with the - // non-JSR normal-branch stuff occurring below. - if (is_jsr) { - // Pre-load the next target bytecode into EBX - __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0)); - - // compute return address as bci in rax, - __ lea(rax, at_bcp((is_wide ? 5 : 3) - in_bytes(ConstMethod::codes_offset()))); - __ subptr(rax, Address(rcx, Method::const_offset())); - // Adjust the bcp in RSI by the displacement in EDX - __ addptr(rsi, rdx); - // Push return address - __ push_i(rax); - // jsr returns vtos - __ dispatch_only_noverify(vtos); - return; - } - - // Normal (non-jsr) branch handling - - // Adjust the bcp in RSI by the displacement in EDX - __ addptr(rsi, rdx); - - assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters"); - Label backedge_counter_overflow; - Label profile_method; - Label dispatch; - if (UseLoopCounter) { - // increment backedge counter for backward branches - // rax,: MDO - // rbx,: MDO bumped taken-count - // rcx: method - // rdx: target offset - // rsi: target bcp - // rdi: locals pointer - __ testl(rdx, rdx); // check if forward or backward branch - __ jcc(Assembler::positive, dispatch); // count only if backward branch - - // check if MethodCounters exists - Label has_counters; - __ movptr(rax, Address(rcx, Method::method_counters_offset())); - __ testptr(rax, rax); - __ jcc(Assembler::notZero, has_counters); - __ push(rdx); - __ push(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), - rcx); - __ pop(rcx); - __ pop(rdx); - __ movptr(rax, Address(rcx, Method::method_counters_offset())); - __ testptr(rax, rax); - __ jcc(Assembler::zero, dispatch); - __ bind(has_counters); - - if (TieredCompilation) { - Label no_mdo; - int increment = InvocationCounter::count_increment; - if (ProfileInterpreter) { - // Are we profiling? - __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset()))); - __ testptr(rbx, rbx); - __ jccb(Assembler::zero, no_mdo); - // Increment the MDO backedge counter - const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) + - in_bytes(InvocationCounter::counter_offset())); - const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset())); - __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, - rax, false, Assembler::zero, &backedge_counter_overflow); - __ jmp(dispatch); - } - __ bind(no_mdo); - // Increment backedge counter in MethodCounters* - __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); - __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask, - rax, false, Assembler::zero, &backedge_counter_overflow); - } else { // not TieredCompilation - // increment counter - __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - __ movl(rax, Address(rcx, be_offset)); // load backedge counter - __ incrementl(rax, InvocationCounter::count_increment); // increment counter - __ movl(Address(rcx, be_offset), rax); // store counter - - __ movl(rax, Address(rcx, inv_offset)); // load invocation counter - - __ andl(rax, InvocationCounter::count_mask_value); // and the status bits - __ addl(rax, Address(rcx, be_offset)); // add both counters - - if (ProfileInterpreter) { - // Test to see if we should create a method data oop - __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); - __ jcc(Assembler::less, dispatch); - - // if no method data exists, go to profile method - __ test_method_data_pointer(rax, profile_method); - - if (UseOnStackReplacement) { - // check for overflow against rbx, which is the MDO taken count - __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); - __ jcc(Assembler::below, dispatch); - - // When ProfileInterpreter is on, the backedge_count comes from the - // MethodData*, which value does not get reset on the call to - // frequency_counter_overflow(). To avoid excessive calls to the overflow - // routine while the method is being compiled, add a second test to make - // sure the overflow function is called only once every overflow_frequency. - const int overflow_frequency = 1024; - __ andptr(rbx, overflow_frequency-1); - __ jcc(Assembler::zero, backedge_counter_overflow); - } - } else { - if (UseOnStackReplacement) { - // check for overflow against rax, which is the sum of the counters - __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); - __ jcc(Assembler::aboveEqual, backedge_counter_overflow); - - } - } - } - __ bind(dispatch); - } - - // Pre-load the next target bytecode into EBX - __ load_unsigned_byte(rbx, Address(rsi, 0)); - - // continue with the bytecode @ target - // rax,: return bci for jsr's, unused otherwise - // rbx,: target bytecode - // rsi: target bcp - __ dispatch_only(vtos); - - if (UseLoopCounter) { - if (ProfileInterpreter) { - // Out-of-line code to allocate method data oop. - __ bind(profile_method); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); - __ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode - __ set_method_data_pointer_for_bcp(); - __ jmp(dispatch); - } - - if (UseOnStackReplacement) { - - // invocation counter overflow - __ bind(backedge_counter_overflow); - __ negptr(rdx); - __ addptr(rdx, rsi); // branch bcp - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rdx); - __ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode - - // rax,: osr nmethod (osr ok) or NULL (osr not possible) - // rbx,: target bytecode - // rdx: scratch - // rdi: locals pointer - // rsi: bcp - __ testptr(rax, rax); // test result - __ jcc(Assembler::zero, dispatch); // no osr if null - // nmethod may have been invalidated (VM may block upon call_VM return) - __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use); - __ jcc(Assembler::notEqual, dispatch); - - // We have the address of an on stack replacement routine in rax, - // We need to prepare to execute the OSR method. First we must - // migrate the locals and monitors off of the stack. - - __ mov(rbx, rax); // save the nmethod - - __ get_thread(rcx); - call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); - // rax, is OSR buffer, move it to expected parameter location - __ mov(rcx, rax); - - // pop the interpreter frame - __ movptr(rdx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp - __ leave(); // remove frame anchor - __ pop(rdi); // get return address - __ mov(rsp, rdx); // set sp to sender sp - - // Align stack pointer for compiled code (note that caller is - // responsible for undoing this fixup by remembering the old SP - // in an rbp,-relative location) - __ andptr(rsp, -(StackAlignmentInBytes)); - - // push the (possibly adjusted) return address - __ push(rdi); - - // and begin the OSR nmethod - __ jmp(Address(rbx, nmethod::osr_entry_point_offset())); - } - } -} - - -void TemplateTable::if_0cmp(Condition cc) { - transition(itos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ testl(rax, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::if_icmp(Condition cc) { - transition(itos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ pop_i(rdx); - __ cmpl(rdx, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::if_nullcmp(Condition cc) { - transition(atos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ testptr(rax, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::if_acmp(Condition cc) { - transition(atos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ pop_ptr(rdx); - __ cmpptr(rdx, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - - -void TemplateTable::ret() { - transition(vtos, vtos); - locals_index(rbx); - __ movptr(rbx, iaddress(rbx)); // get return bci, compute return bcp - __ profile_ret(rbx, rcx); - __ get_method(rax); - __ movptr(rsi, Address(rax, Method::const_offset())); - __ lea(rsi, Address(rsi, rbx, Address::times_1, - ConstMethod::codes_offset())); - __ dispatch_next(vtos); -} - - -void TemplateTable::wide_ret() { - transition(vtos, vtos); - locals_index_wide(rbx); - __ movptr(rbx, iaddress(rbx)); // get return bci, compute return bcp - __ profile_ret(rbx, rcx); - __ get_method(rax); - __ movptr(rsi, Address(rax, Method::const_offset())); - __ lea(rsi, Address(rsi, rbx, Address::times_1, ConstMethod::codes_offset())); - __ dispatch_next(vtos); -} - - -void TemplateTable::tableswitch() { - Label default_case, continue_execution; - transition(itos, vtos); - // align rsi - __ lea(rbx, at_bcp(wordSize)); - __ andptr(rbx, -wordSize); - // load lo & hi - __ movl(rcx, Address(rbx, 1 * wordSize)); - __ movl(rdx, Address(rbx, 2 * wordSize)); - __ bswapl(rcx); - __ bswapl(rdx); - // check against lo & hi - __ cmpl(rax, rcx); - __ jccb(Assembler::less, default_case); - __ cmpl(rax, rdx); - __ jccb(Assembler::greater, default_case); - // lookup dispatch offset - __ subl(rax, rcx); - __ movl(rdx, Address(rbx, rax, Address::times_4, 3 * BytesPerInt)); - __ profile_switch_case(rax, rbx, rcx); - // continue execution - __ bind(continue_execution); - __ bswapl(rdx); - __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1)); - __ addptr(rsi, rdx); - __ dispatch_only(vtos); - // handle default - __ bind(default_case); - __ profile_switch_default(rax); - __ movl(rdx, Address(rbx, 0)); - __ jmp(continue_execution); -} - - -void TemplateTable::lookupswitch() { - transition(itos, itos); - __ stop("lookupswitch bytecode should have been rewritten"); -} - - -void TemplateTable::fast_linearswitch() { - transition(itos, vtos); - Label loop_entry, loop, found, continue_execution; - // bswapl rax, so we can avoid bswapping the table entries - __ bswapl(rax); - // align rsi - __ lea(rbx, at_bcp(wordSize)); // btw: should be able to get rid of this instruction (change offsets below) - __ andptr(rbx, -wordSize); - // set counter - __ movl(rcx, Address(rbx, wordSize)); - __ bswapl(rcx); - __ jmpb(loop_entry); - // table search - __ bind(loop); - __ cmpl(rax, Address(rbx, rcx, Address::times_8, 2 * wordSize)); - __ jccb(Assembler::equal, found); - __ bind(loop_entry); - __ decrementl(rcx); - __ jcc(Assembler::greaterEqual, loop); - // default case - __ profile_switch_default(rax); - __ movl(rdx, Address(rbx, 0)); - __ jmpb(continue_execution); - // entry found -> get offset - __ bind(found); - __ movl(rdx, Address(rbx, rcx, Address::times_8, 3 * wordSize)); - __ profile_switch_case(rcx, rax, rbx); - // continue execution - __ bind(continue_execution); - __ bswapl(rdx); - __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1)); - __ addptr(rsi, rdx); - __ dispatch_only(vtos); -} - - -void TemplateTable::fast_binaryswitch() { - transition(itos, vtos); - // Implementation using the following core algorithm: - // - // int binary_search(int key, LookupswitchPair* array, int n) { - // // Binary search according to "Methodik des Programmierens" by - // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985. - // int i = 0; - // int j = n; - // while (i+1 < j) { - // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q) - // // with Q: for all i: 0 <= i < n: key < a[i] - // // where a stands for the array and assuming that the (inexisting) - // // element a[n] is infinitely big. - // int h = (i + j) >> 1; - // // i < h < j - // if (key < array[h].fast_match()) { - // j = h; - // } else { - // i = h; - // } - // } - // // R: a[i] <= key < a[i+1] or Q - // // (i.e., if key is within array, i is the correct index) - // return i; - // } - - // register allocation - const Register key = rax; // already set (tosca) - const Register array = rbx; - const Register i = rcx; - const Register j = rdx; - const Register h = rdi; // needs to be restored - const Register temp = rsi; - // setup array - __ save_bcp(); - - __ lea(array, at_bcp(3*wordSize)); // btw: should be able to get rid of this instruction (change offsets below) - __ andptr(array, -wordSize); - // initialize i & j - __ xorl(i, i); // i = 0; - __ movl(j, Address(array, -wordSize)); // j = length(array); - // Convert j into native byteordering - __ bswapl(j); - // and start - Label entry; - __ jmp(entry); - - // binary search loop - { Label loop; - __ bind(loop); - // int h = (i + j) >> 1; - __ leal(h, Address(i, j, Address::times_1)); // h = i + j; - __ sarl(h, 1); // h = (i + j) >> 1; - // if (key < array[h].fast_match()) { - // j = h; - // } else { - // i = h; - // } - // Convert array[h].match to native byte-ordering before compare - __ movl(temp, Address(array, h, Address::times_8, 0*wordSize)); - __ bswapl(temp); - __ cmpl(key, temp); - // j = h if (key < array[h].fast_match()) - __ cmov32(Assembler::less , j, h); - // i = h if (key >= array[h].fast_match()) - __ cmov32(Assembler::greaterEqual, i, h); - // while (i+1 < j) - __ bind(entry); - __ leal(h, Address(i, 1)); // i+1 - __ cmpl(h, j); // i+1 < j - __ jcc(Assembler::less, loop); - } - - // end of binary search, result index is i (must check again!) - Label default_case; - // Convert array[i].match to native byte-ordering before compare - __ movl(temp, Address(array, i, Address::times_8, 0*wordSize)); - __ bswapl(temp); - __ cmpl(key, temp); - __ jcc(Assembler::notEqual, default_case); - - // entry found -> j = offset - __ movl(j , Address(array, i, Address::times_8, 1*wordSize)); - __ profile_switch_case(i, key, array); - __ bswapl(j); - LP64_ONLY(__ movslq(j, j)); - __ restore_bcp(); - __ restore_locals(); // restore rdi - __ load_unsigned_byte(rbx, Address(rsi, j, Address::times_1)); - - __ addptr(rsi, j); - __ dispatch_only(vtos); - - // default case -> j = default offset - __ bind(default_case); - __ profile_switch_default(i); - __ movl(j, Address(array, -2*wordSize)); - __ bswapl(j); - LP64_ONLY(__ movslq(j, j)); - __ restore_bcp(); - __ restore_locals(); // restore rdi - __ load_unsigned_byte(rbx, Address(rsi, j, Address::times_1)); - __ addptr(rsi, j); - __ dispatch_only(vtos); -} - - -void TemplateTable::_return(TosState state) { - transition(state, state); - assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation - - if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { - assert(state == vtos, "only valid state"); - __ movptr(rax, aaddress(0)); - __ load_klass(rdi, rax); - __ movl(rdi, Address(rdi, Klass::access_flags_offset())); - __ testl(rdi, JVM_ACC_HAS_FINALIZER); - Label skip_register_finalizer; - __ jcc(Assembler::zero, skip_register_finalizer); - - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), rax); - - __ bind(skip_register_finalizer); - } - - __ remove_activation(state, rsi); - __ jmp(rsi); -} - - -// ---------------------------------------------------------------------------- -// Volatile variables demand their effects be made known to all CPU's in -// order. Store buffers on most chips allow reads & writes to reorder; the -// JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of -// memory barrier (i.e., it's not sufficient that the interpreter does not -// reorder volatile references, the hardware also must not reorder them). -// -// According to the new Java Memory Model (JMM): -// (1) All volatiles are serialized wrt to each other. -// ALSO reads & writes act as aquire & release, so: -// (2) A read cannot let unrelated NON-volatile memory refs that happen after -// the read float up to before the read. It's OK for non-volatile memory refs -// that happen before the volatile read to float down below it. -// (3) Similar a volatile write cannot let unrelated NON-volatile memory refs -// that happen BEFORE the write float down to after the write. It's OK for -// non-volatile memory refs that happen after the volatile write to float up -// before it. -// -// We only put in barriers around volatile refs (they are expensive), not -// _between_ memory refs (that would require us to track the flavor of the -// previous memory refs). Requirements (2) and (3) require some barriers -// before volatile stores and after volatile loads. These nearly cover -// requirement (1) but miss the volatile-store-volatile-load case. This final -// case is placed after volatile-stores although it could just as well go -// before volatile-loads. -void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constraint ) { - // Helper function to insert a is-volatile test and memory barrier - if( !os::is_MP() ) return; // Not needed on single CPU - __ membar(order_constraint); -} - -void TemplateTable::resolve_cache_and_index(int byte_no, - Register Rcache, - Register index, - size_t index_size) { - const Register temp = rbx; - assert_different_registers(Rcache, index, temp); - - Label resolved; - assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size); - __ cmpl(temp, (int) bytecode()); // have we resolved this bytecode? - __ jcc(Assembler::equal, resolved); - - // resolve first time through - address entry; - switch (bytecode()) { - case Bytecodes::_getstatic : // fall through - case Bytecodes::_putstatic : // fall through - case Bytecodes::_getfield : // fall through - case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; - case Bytecodes::_invokevirtual : // fall through - case Bytecodes::_invokespecial : // fall through - case Bytecodes::_invokestatic : // fall through - case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; - case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break; - case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; - default: - fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); - break; - } - __ movl(temp, (int)bytecode()); - __ call_VM(noreg, entry, temp); - // Update registers with resolved info - __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); - __ bind(resolved); -} - - -// The cache and index registers must be set before call -void TemplateTable::load_field_cp_cache_entry(Register obj, - Register cache, - Register index, - Register off, - Register flags, - bool is_static = false) { - assert_different_registers(cache, index, flags, off); - - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - // Field offset - __ movptr(off, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()))); - // Flags - __ movl(flags, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()))); - - // klass overwrite register - if (is_static) { - __ movptr(obj, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset()))); - const int mirror_offset = in_bytes(Klass::java_mirror_offset()); - __ movptr(obj, Address(obj, mirror_offset)); - } -} - -void TemplateTable::load_invoke_cp_cache_entry(int byte_no, - Register method, - Register itable_index, - Register flags, - bool is_invokevirtual, - bool is_invokevfinal, /*unused*/ - bool is_invokedynamic) { - // setup registers - const Register cache = rcx; - const Register index = rdx; - assert_different_registers(method, flags); - assert_different_registers(method, cache, index); - assert_different_registers(itable_index, flags); - assert_different_registers(itable_index, cache, index); - // determine constant pool cache field offsets - assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant"); - const int method_offset = in_bytes( - ConstantPoolCache::base_offset() + - ((byte_no == f2_byte) - ? ConstantPoolCacheEntry::f2_offset() - : ConstantPoolCacheEntry::f1_offset())); - const int flags_offset = in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::flags_offset()); - // access constant pool cache fields - const int index_offset = in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::f2_offset()); - - size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); - resolve_cache_and_index(byte_no, cache, index, index_size); - __ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); - - if (itable_index != noreg) { - __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset)); - } - __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); -} - - -// The registers cache and index expected to be set before call. -// Correct values of the cache and index registers are preserved. -void TemplateTable::jvmti_post_field_access(Register cache, - Register index, - bool is_static, - bool has_tos) { - if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we take - // the time to call into the VM. - Label L1; - assert_different_registers(cache, index, rax); - __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rax,rax); - __ jcc(Assembler::zero, L1); - - // cache entry pointer - __ addptr(cache, in_bytes(ConstantPoolCache::base_offset())); - __ shll(index, LogBytesPerWord); - __ addptr(cache, index); - if (is_static) { - __ xorptr(rax, rax); // NULL object reference - } else { - __ pop(atos); // Get the object - __ verify_oop(rax); - __ push(atos); // Restore stack state - } - // rax,: object pointer or NULL - // cache: cache entry pointer - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), - rax, cache); - __ get_cache_and_index_at_bcp(cache, index, 1); - __ bind(L1); - } -} - -void TemplateTable::pop_and_check_object(Register r) { - __ pop_ptr(r); - __ null_check(r); // for field access must check obj. - __ verify_oop(r); -} - -void TemplateTable::getfield_or_static(int byte_no, bool is_static) { - transition(vtos, vtos); - - const Register cache = rcx; - const Register index = rdx; - const Register obj = rcx; - const Register off = rbx; - const Register flags = rax; - - resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); - jvmti_post_field_access(cache, index, is_static, false); - load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - - if (!is_static) pop_and_check_object(obj); - - const Address lo(obj, off, Address::times_1, 0*wordSize); - const Address hi(obj, off, Address::times_1, 1*wordSize); - - Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; - - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - assert(btos == 0, "change code, btos != 0"); - // btos - __ andptr(flags, ConstantPoolCacheEntry::tos_state_mask); - __ jcc(Assembler::notZero, notByte); - - __ load_signed_byte(rax, lo ); - __ push(btos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_bgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notByte); - // itos - __ cmpl(flags, itos ); - __ jcc(Assembler::notEqual, notInt); - - __ movl(rax, lo ); - __ push(itos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_igetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notInt); - // atos - __ cmpl(flags, atos ); - __ jcc(Assembler::notEqual, notObj); - - __ movl(rax, lo ); - __ push(atos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_agetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notObj); - // ctos - __ cmpl(flags, ctos ); - __ jcc(Assembler::notEqual, notChar); - - __ load_unsigned_short(rax, lo ); - __ push(ctos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notChar); - // stos - __ cmpl(flags, stos ); - __ jcc(Assembler::notEqual, notShort); - - __ load_signed_short(rax, lo ); - __ push(stos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notShort); - // ltos - __ cmpl(flags, ltos ); - __ jcc(Assembler::notEqual, notLong); - - // Generate code as if volatile. There just aren't enough registers to - // save that information and this code is faster than the test. - __ fild_d(lo); // Must load atomically - __ subptr(rsp,2*wordSize); // Make space for store - __ fistp_d(Address(rsp,0)); - __ pop(rax); - __ pop(rdx); - - __ push(ltos); - // Don't rewrite to _fast_lgetfield for potential volatile case. - __ jmp(Done); - - __ bind(notLong); - // ftos - __ cmpl(flags, ftos ); - __ jcc(Assembler::notEqual, notFloat); - - __ fld_s(lo); - __ push(ftos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_fgetfield, rcx, rbx); - } - __ jmp(Done); - - __ bind(notFloat); - // dtos - __ cmpl(flags, dtos ); - __ jcc(Assembler::notEqual, notDouble); - - __ fld_d(lo); - __ push(dtos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_dgetfield, rcx, rbx); - } - __ jmpb(Done); - - __ bind(notDouble); - - __ stop("Bad state"); - - __ bind(Done); - // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO). - // volatile_barrier( ); -} - - -void TemplateTable::getfield(int byte_no) { - getfield_or_static(byte_no, false); -} - - -void TemplateTable::getstatic(int byte_no) { - getfield_or_static(byte_no, true); -} - -// The registers cache and index expected to be set before call. -// The function may destroy various registers, just not the cache and index registers. -void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { - - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - - if (JvmtiExport::can_post_field_modification()) { - // Check to see if a field modification watch has been set before we take - // the time to call into the VM. - Label L1; - assert_different_registers(cache, index, rax); - __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(rax, rax); - __ jcc(Assembler::zero, L1); - - // The cache and index registers have been already set. - // This allows to eliminate this call but the cache and index - // registers have to be correspondingly used after this line. - __ get_cache_and_index_at_bcp(rax, rdx, 1); - - if (is_static) { - // Life is simple. Null out the object pointer. - __ xorptr(rbx, rbx); - } else { - // Life is harder. The stack holds the value on top, followed by the object. - // We don't know the size of the value, though; it could be one or two words - // depending on its type. As a result, we must find the type to determine where - // the object is. - Label two_word, valsize_known; - __ movl(rcx, Address(rax, rdx, Address::times_ptr, in_bytes(cp_base_offset + - ConstantPoolCacheEntry::flags_offset()))); - __ mov(rbx, rsp); - __ shrl(rcx, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask rcx after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - __ cmpl(rcx, ltos); - __ jccb(Assembler::equal, two_word); - __ cmpl(rcx, dtos); - __ jccb(Assembler::equal, two_word); - __ addptr(rbx, Interpreter::expr_offset_in_bytes(1)); // one word jvalue (not ltos, dtos) - __ jmpb(valsize_known); - - __ bind(two_word); - __ addptr(rbx, Interpreter::expr_offset_in_bytes(2)); // two words jvalue - - __ bind(valsize_known); - // setup object pointer - __ movptr(rbx, Address(rbx, 0)); - } - // cache entry pointer - __ addptr(rax, in_bytes(cp_base_offset)); - __ shll(rdx, LogBytesPerWord); - __ addptr(rax, rdx); - // object (tos) - __ mov(rcx, rsp); - // rbx,: object pointer set up above (NULL if static) - // rax,: cache entry pointer - // rcx: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), - rbx, rax, rcx); - __ get_cache_and_index_at_bcp(cache, index, 1); - __ bind(L1); - } -} - - -void TemplateTable::putfield_or_static(int byte_no, bool is_static) { - transition(vtos, vtos); - - const Register cache = rcx; - const Register index = rdx; - const Register obj = rcx; - const Register off = rbx; - const Register flags = rax; - - resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); - jvmti_post_field_mod(cache, index, is_static); - load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - - // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO). - // volatile_barrier( ); - - Label notVolatile, Done; - __ movl(rdx, flags); - __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - __ andl(rdx, 0x1); - - // field addresses - const Address lo(obj, off, Address::times_1, 0*wordSize); - const Address hi(obj, off, Address::times_1, 1*wordSize); - - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; - - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - assert(btos == 0, "change code, btos != 0"); - __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); - __ jcc(Assembler::notZero, notByte); - - // btos - { - __ pop(btos); - if (!is_static) pop_and_check_object(obj); - __ movb(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_bputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notByte); - __ cmpl(flags, itos); - __ jcc(Assembler::notEqual, notInt); - - // itos - { - __ pop(itos); - if (!is_static) pop_and_check_object(obj); - __ movl(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_iputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notInt); - __ cmpl(flags, atos); - __ jcc(Assembler::notEqual, notObj); - - // atos - { - __ pop(atos); - if (!is_static) pop_and_check_object(obj); - do_oop_store(_masm, lo, rax, _bs->kind(), false); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notObj); - __ cmpl(flags, ctos); - __ jcc(Assembler::notEqual, notChar); - - // ctos - { - __ pop(ctos); - if (!is_static) pop_and_check_object(obj); - __ movw(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_cputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notChar); - __ cmpl(flags, stos); - __ jcc(Assembler::notEqual, notShort); - - // stos - { - __ pop(stos); - if (!is_static) pop_and_check_object(obj); - __ movw(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_sputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notShort); - __ cmpl(flags, ltos); - __ jcc(Assembler::notEqual, notLong); - - // ltos - { - Label notVolatileLong; - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatileLong); - - __ pop(ltos); // overwrites rdx, do this after testing volatile. - if (!is_static) pop_and_check_object(obj); - - // Replace with real volatile test - __ push(rdx); - __ push(rax); // Must update atomically with FIST - __ fild_d(Address(rsp,0)); // So load into FPU register - __ fistp_d(lo); // and put into memory atomically - __ addptr(rsp, 2*wordSize); - // volatile_barrier(); - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - // Don't rewrite volatile version - __ jmp(notVolatile); - - __ bind(notVolatileLong); - - __ pop(ltos); // overwrites rdx - if (!is_static) pop_and_check_object(obj); - NOT_LP64(__ movptr(hi, rdx)); - __ movptr(lo, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_lputfield, rcx, rbx, true, byte_no); - } - __ jmp(notVolatile); - } - - __ bind(notLong); - __ cmpl(flags, ftos); - __ jcc(Assembler::notEqual, notFloat); - - // ftos - { - __ pop(ftos); - if (!is_static) pop_and_check_object(obj); - __ fstp_s(lo); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_fputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notFloat); -#ifdef ASSERT - __ cmpl(flags, dtos); - __ jcc(Assembler::notEqual, notDouble); -#endif - - // dtos - { - __ pop(dtos); - if (!is_static) pop_and_check_object(obj); - __ fstp_d(lo); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_dputfield, rcx, rbx, true, byte_no); - } - __ jmp(Done); - } - -#ifdef ASSERT - __ bind(notDouble); - __ stop("Bad state"); -#endif - - __ bind(Done); - - // Check for volatile store - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatile); - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - __ bind(notVolatile); -} - - -void TemplateTable::putfield(int byte_no) { - putfield_or_static(byte_no, false); -} - - -void TemplateTable::putstatic(int byte_no) { - putfield_or_static(byte_no, true); -} - -void TemplateTable::jvmti_post_fast_field_mod() { - if (JvmtiExport::can_post_field_modification()) { - // Check to see if a field modification watch has been set before we take - // the time to call into the VM. - Label L2; - __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(rcx,rcx); - __ jcc(Assembler::zero, L2); - __ pop_ptr(rbx); // copy the object pointer from tos - __ verify_oop(rbx); - __ push_ptr(rbx); // put the object pointer back on tos - - // Save tos values before call_VM() clobbers them. Since we have - // to do it for every data type, we use the saved values as the - // jvalue object. - switch (bytecode()) { // load values into the jvalue object - case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; - case Bytecodes::_fast_bputfield: // fall through - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: // fall through - case Bytecodes::_fast_iputfield: __ push_i(rax); break; - case Bytecodes::_fast_dputfield: __ push_d(); break; - case Bytecodes::_fast_fputfield: __ push_f(); break; - case Bytecodes::_fast_lputfield: __ push_l(rax); break; - - default: - ShouldNotReachHere(); - } - __ mov(rcx, rsp); // points to jvalue on the stack - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(rax, rdx, 1); - __ verify_oop(rbx); - // rbx,: object pointer copied above - // rax,: cache entry pointer - // rcx: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx); - - switch (bytecode()) { // restore tos values - case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; - case Bytecodes::_fast_bputfield: // fall through - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: // fall through - case Bytecodes::_fast_iputfield: __ pop_i(rax); break; - case Bytecodes::_fast_dputfield: __ pop_d(); break; - case Bytecodes::_fast_fputfield: __ pop_f(); break; - case Bytecodes::_fast_lputfield: __ pop_l(rax); break; - } - __ bind(L2); - } -} - -void TemplateTable::fast_storefield(TosState state) { - transition(state, vtos); - - ByteSize base = ConstantPoolCache::base_offset(); - - jvmti_post_fast_field_mod(); - - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rbx, 1); - - // test for volatile with rdx but rdx is tos register for lputfield. - if (bytecode() == Bytecodes::_fast_lputfield) __ push(rdx); - __ movl(rdx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + - ConstantPoolCacheEntry::flags_offset()))); - - // replace index with field offset from cache entry - __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + ConstantPoolCacheEntry::f2_offset()))); - - // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO). - // volatile_barrier( ); - - Label notVolatile, Done; - __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - __ andl(rdx, 0x1); - // Check for volatile store - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatile); - - if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx); - - // Get object from stack - pop_and_check_object(rcx); - - // field addresses - const Address lo(rcx, rbx, Address::times_1, 0*wordSize); - const Address hi(rcx, rbx, Address::times_1, 1*wordSize); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_bputfield: __ movb(lo, rax); break; - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; - case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; - case Bytecodes::_fast_lputfield: - NOT_LP64(__ movptr(hi, rdx)); - __ movptr(lo, rax); - break; - case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; - case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; - case Bytecodes::_fast_aputfield: { - do_oop_store(_masm, lo, rax, _bs->kind(), false); - break; - } - default: - ShouldNotReachHere(); - } - - Label done; - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - // Barriers are so large that short branch doesn't reach! - __ jmp(done); - - // Same code as above, but don't need rdx to test for volatile. - __ bind(notVolatile); - - if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx); - - // Get object from stack - pop_and_check_object(rcx); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_bputfield: __ movb(lo, rax); break; - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; - case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; - case Bytecodes::_fast_lputfield: - NOT_LP64(__ movptr(hi, rdx)); - __ movptr(lo, rax); - break; - case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; - case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; - case Bytecodes::_fast_aputfield: { - do_oop_store(_masm, lo, rax, _bs->kind(), false); - break; - } - default: - ShouldNotReachHere(); - } - __ bind(done); -} - - -void TemplateTable::fast_accessfield(TosState state) { - transition(atos, state); - - // do the JVMTI work here to avoid disturbing the register state below - if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we take - // the time to call into the VM. - Label L1; - __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rcx,rcx); - __ jcc(Assembler::zero, L1); - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(rcx, rdx, 1); - __ push_ptr(rax); // save object pointer before call_VM() clobbers it - __ verify_oop(rax); - // rax,: object pointer copied above - // rcx: cache entry pointer - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), rax, rcx); - __ pop_ptr(rax); // restore object pointer - __ bind(L1); - } - - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rbx, 1); - // replace index with field offset from cache entry - __ movptr(rbx, Address(rcx, - rbx, - Address::times_ptr, - in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); - - - // rax,: object - __ verify_oop(rax); - __ null_check(rax); - // field addresses - const Address lo = Address(rax, rbx, Address::times_1, 0*wordSize); - const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo ); break; - case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo ); break; - case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo ); break; - case Bytecodes::_fast_igetfield: __ movl(rax, lo); break; - case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten"); break; - case Bytecodes::_fast_fgetfield: __ fld_s(lo); break; - case Bytecodes::_fast_dgetfield: __ fld_d(lo); break; - case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break; - default: - ShouldNotReachHere(); - } - - // Doug Lea believes this is not needed with current Sparcs(TSO) and Intel(PSO) - // volatile_barrier( ); -} - -void TemplateTable::fast_xaccess(TosState state) { - transition(vtos, state); - // get receiver - __ movptr(rax, aaddress(0)); - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rdx, 2); - __ movptr(rbx, Address(rcx, - rdx, - Address::times_ptr, - in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); - // make sure exception is reported in correct bcp range (getfield is next instruction) - __ increment(rsi); - __ null_check(rax); - const Address lo = Address(rax, rbx, Address::times_1, 0*wordSize); - if (state == itos) { - __ movl(rax, lo); - } else if (state == atos) { - __ movptr(rax, lo); - __ verify_oop(rax); - } else if (state == ftos) { - __ fld_s(lo); - } else { - ShouldNotReachHere(); - } - __ decrement(rsi); -} - - - -//---------------------------------------------------------------------------------------------------- -// Calls - -void TemplateTable::count_calls(Register method, Register temp) { - // implemented elsewhere - ShouldNotReachHere(); -} - - -void TemplateTable::prepare_invoke(int byte_no, - Register method, // linked method (or i-klass) - Register index, // itable index, MethodType, etc. - Register recv, // if caller wants to see it - Register flags // if caller wants to test it - ) { - // determine flags - const Bytecodes::Code code = bytecode(); - const bool is_invokeinterface = code == Bytecodes::_invokeinterface; - const bool is_invokedynamic = code == Bytecodes::_invokedynamic; - const bool is_invokehandle = code == Bytecodes::_invokehandle; - const bool is_invokevirtual = code == Bytecodes::_invokevirtual; - const bool is_invokespecial = code == Bytecodes::_invokespecial; - const bool load_receiver = (recv != noreg); - const bool save_flags = (flags != noreg); - assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); - assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); - assert(flags == noreg || flags == rdx, ""); - assert(recv == noreg || recv == rcx, ""); - - // setup registers & access constant pool cache - if (recv == noreg) recv = rcx; - if (flags == noreg) flags = rdx; - assert_different_registers(method, index, recv, flags); - - // save 'interpreter return address' - __ save_bcp(); - - load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); - - // maybe push appendix to arguments (just before return address) - if (is_invokedynamic || is_invokehandle) { - Label L_no_push; - __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift)); - __ jccb(Assembler::zero, L_no_push); - // Push the appendix as a trailing parameter. - // This must be done before we get the receiver, - // since the parameter_size includes it. - __ push(rbx); - __ mov(rbx, index); - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); - __ load_resolved_reference_at_index(index, rbx); - __ pop(rbx); - __ push(index); // push appendix (MethodType, CallSite, etc.) - __ bind(L_no_push); - } - - // load receiver if needed (note: no return address pushed yet) - if (load_receiver) { - __ movl(recv, flags); - __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask); - const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address - const int receiver_is_at_end = -1; // back off one slot to get receiver - Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end); - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } - - if (save_flags) { - __ mov(rsi, flags); - } - - // compute return type - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask flags after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - // load return address - { - const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); - ExternalAddress table(table_addr); - __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))); - } - - // push return address - __ push(flags); - - // Restore flags value from the constant pool cache, and restore rsi - // for later null checks. rsi is the bytecode pointer - if (save_flags) { - __ mov(flags, rsi); - __ restore_bcp(); - } -} - - -void TemplateTable::invokevirtual_helper(Register index, - Register recv, - Register flags) { - // Uses temporary registers rax, rdx - assert_different_registers(index, recv, rax, rdx); - assert(index == rbx, ""); - assert(recv == rcx, ""); - - // Test for an invoke of a final method - Label notFinal; - __ movl(rax, flags); - __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); - __ jcc(Assembler::zero, notFinal); - - const Register method = index; // method must be rbx - assert(method == rbx, - "Method* must be rbx for interpreter calling convention"); - - // do the call - the index is actually the method to call - // that is, f2 is a vtable index if !is_vfinal, else f2 is a Method* - - // It's final, need a null check here! - __ null_check(recv); - - // profile this call - __ profile_final_call(rax); - __ profile_arguments_type(rax, method, rsi, true); - - __ jump_from_interpreted(method, rax); - - __ bind(notFinal); - - // get receiver klass - __ null_check(recv, oopDesc::klass_offset_in_bytes()); - __ load_klass(rax, recv); - - // profile this call - __ profile_virtual_call(rax, rdi, rdx); - - // get target Method* & entry point - __ lookup_virtual_method(rax, index, method); - __ profile_arguments_type(rdx, method, rsi, true); - __ jump_from_interpreted(method, rdx); -} - - -void TemplateTable::invokevirtual(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f2_byte, "use this argument"); - prepare_invoke(byte_no, - rbx, // method or vtable index - noreg, // unused itable index - rcx, rdx); // recv, flags - - // rbx: index - // rcx: receiver - // rdx: flags - - invokevirtual_helper(rbx, rcx, rdx); -} - - -void TemplateTable::invokespecial(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rbx, noreg, // get f1 Method* - rcx); // get receiver also for null check - __ verify_oop(rcx); - __ null_check(rcx); - // do the call - __ profile_call(rax); - __ profile_arguments_type(rax, rbx, rsi, false); - __ jump_from_interpreted(rbx, rax); -} - - -void TemplateTable::invokestatic(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rbx); // get f1 Method* - // do the call - __ profile_call(rax); - __ profile_arguments_type(rax, rbx, rsi, false); - __ jump_from_interpreted(rbx, rax); -} - - -void TemplateTable::fast_invokevfinal(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f2_byte, "use this argument"); - __ stop("fast_invokevfinal not used on x86"); -} - - -void TemplateTable::invokeinterface(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index - rcx, rdx); // recv, flags - - // rax: interface klass (from f1) - // rbx: itable index (from f2) - // rcx: receiver - // rdx: flags - - // Special case of invokeinterface called for virtual method of - // java.lang.Object. See cpCacheOop.cpp for details. - // This code isn't produced by javac, but could be produced by - // another compliant java compiler. - Label notMethod; - __ movl(rdi, rdx); - __ andl(rdi, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); - __ jcc(Assembler::zero, notMethod); - - invokevirtual_helper(rbx, rcx, rdx); - __ bind(notMethod); - - // Get receiver klass into rdx - also a null check - __ restore_locals(); // restore rdi - __ null_check(rcx, oopDesc::klass_offset_in_bytes()); - __ load_klass(rdx, rcx); - - // profile this call - __ profile_virtual_call(rdx, rsi, rdi); - - Label no_such_interface, no_such_method; - - __ lookup_interface_method(// inputs: rec. class, interface, itable index - rdx, rax, rbx, - // outputs: method, scan temp. reg - rbx, rsi, - no_such_interface); - - // rbx: Method* to call - // rcx: receiver - // Check for abstract method error - // Note: This should be done more efficiently via a throw_abstract_method_error - // interpreter entry point and a conditional jump to it in case of a null - // method. - __ testptr(rbx, rbx); - __ jcc(Assembler::zero, no_such_method); - - __ profile_arguments_type(rdx, rbx, rsi, true); - - // do the call - // rcx: receiver - // rbx,: Method* - __ jump_from_interpreted(rbx, rdx); - __ should_not_reach_here(); - - // exception handling code follows... - // note: must restore interpreter registers to canonical - // state for exception handling to work correctly! - - __ bind(no_such_method); - // throw exception - __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); - - __ bind(no_such_interface); - // throw exception - __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_IncompatibleClassChangeError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); -} - -void TemplateTable::invokehandle(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - const Register rbx_method = rbx; - const Register rax_mtype = rax; - const Register rcx_recv = rcx; - const Register rdx_flags = rdx; - - prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv); - __ verify_method_ptr(rbx_method); - __ verify_oop(rcx_recv); - __ null_check(rcx_recv); - - // rax: MethodType object (from cpool->resolved_references[f1], if necessary) - // rbx: MH.invokeExact_MT method (from f2) - - // Note: rax_mtype is already pushed (if necessary) by prepare_invoke - - // FIXME: profile the LambdaForm also - __ profile_final_call(rax); - __ profile_arguments_type(rdx, rbx_method, rsi, true); - - __ jump_from_interpreted(rbx_method, rdx); -} - - -void TemplateTable::invokedynamic(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - - const Register rbx_method = rbx; - const Register rax_callsite = rax; - - prepare_invoke(byte_no, rbx_method, rax_callsite); - - // rax: CallSite object (from cpool->resolved_references[f1]) - // rbx: MH.linkToCallSite method (from f2) - - // Note: rax_callsite is already pushed by prepare_invoke - - // %%% should make a type profile for any invokedynamic that takes a ref argument - // profile this call - __ profile_call(rsi); - __ profile_arguments_type(rdx, rbx, rsi, false); - - __ verify_oop(rax_callsite); - - __ jump_from_interpreted(rbx_method, rdx); -} - -//---------------------------------------------------------------------------------------------------- -// Allocation - -void TemplateTable::_new() { - transition(vtos, atos); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - Label slow_case; - Label slow_case_no_pop; - Label done; - Label initialize_header; - Label initialize_object; // including clearing the fields - Label allocate_shared; - - __ get_cpool_and_tags(rcx, rax); - - // Make sure the class we're about to instantiate has been resolved. - // This is done before loading InstanceKlass to be consistent with the order - // how Constant Pool is updated (see ConstantPool::klass_at_put) - const int tags_offset = Array::base_offset_in_bytes(); - __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, slow_case_no_pop); - - // get InstanceKlass - __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool))); - __ push(rcx); // save the contexts of klass for initializing the header - - // make sure klass is initialized & doesn't have finalizer - // make sure klass is fully initialized - __ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized); - __ jcc(Assembler::notEqual, slow_case); - - // get instance_size in InstanceKlass (scaled to a count of bytes) - __ movl(rdx, Address(rcx, Klass::layout_helper_offset())); - // test to see if it has a finalizer or is malformed in some way - __ testl(rdx, Klass::_lh_instance_slow_path_bit); - __ jcc(Assembler::notZero, slow_case); - - // - // Allocate the instance - // 1) Try to allocate in the TLAB - // 2) if fail and the object is large allocate in the shared Eden - // 3) if the above fails (or is not applicable), go to a slow case - // (creates a new TLAB, etc.) - - const bool allow_shared_alloc = - Universe::heap()->supports_inline_contig_alloc(); - - const Register thread = rcx; - if (UseTLAB || allow_shared_alloc) { - __ get_thread(thread); - } - - if (UseTLAB) { - __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset()))); - __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset()))); - __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case); - __ movptr(Address(thread, in_bytes(JavaThread::tlab_top_offset())), rbx); - if (ZeroTLAB) { - // the fields have been already cleared - __ jmp(initialize_header); - } else { - // initialize both the header and fields - __ jmp(initialize_object); - } - } - - // Allocation in the shared Eden, if allowed. - // - // rdx: instance size in bytes - if (allow_shared_alloc) { - __ bind(allocate_shared); - - ExternalAddress heap_top((address)Universe::heap()->top_addr()); - - Label retry; - __ bind(retry); - __ movptr(rax, heap_top); - __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, ExternalAddress((address)Universe::heap()->end_addr())); - __ jcc(Assembler::above, slow_case); - - // Compare rax, with the top addr, and if still equal, store the new - // top addr in rbx, at the address of the top addr pointer. Sets ZF if was - // equal, and clears it otherwise. Use lock prefix for atomicity on MPs. - // - // rax,: object begin - // rbx,: object end - // rdx: instance size in bytes - __ locked_cmpxchgptr(rbx, heap_top); - - // if someone beat us on the allocation, try again, otherwise continue - __ jcc(Assembler::notEqual, retry); - - __ incr_allocated_bytes(thread, rdx, 0); - } - - if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { - // The object is initialized before the header. If the object size is - // zero, go directly to the header initialization. - __ bind(initialize_object); - __ decrement(rdx, sizeof(oopDesc)); - __ jcc(Assembler::zero, initialize_header); - - // Initialize topmost object field, divide rdx by 8, check if odd and - // test if zero. - __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) - __ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd - - // rdx must have been multiple of 8 -#ifdef ASSERT - // make sure rdx was multiple of 8 - Label L; - // Ignore partial flag stall after shrl() since it is debug VM - __ jccb(Assembler::carryClear, L); - __ stop("object size is not multiple of 2 - adjust this code"); - __ bind(L); - // rdx must be > 0, no extra check needed here -#endif - - // initialize remaining object fields: rdx was a multiple of 8 - { Label loop; - __ bind(loop); - __ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 1*oopSize), rcx); - NOT_LP64(__ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 2*oopSize), rcx)); - __ decrement(rdx); - __ jcc(Assembler::notZero, loop); - } - - // initialize object header only. - __ bind(initialize_header); - if (UseBiasedLocking) { - __ pop(rcx); // get saved klass back in the register. - __ movptr(rbx, Address(rcx, Klass::prototype_header_offset())); - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), rbx); - } else { - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), - (int32_t)markOopDesc::prototype()); // header - __ pop(rcx); // get saved klass back in the register. - } - __ store_klass(rax, rcx); // klass - - { - SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0); - // Trigger dtrace event for fastpath - __ push(atos); - __ call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); - __ pop(atos); - } - - __ jmp(done); - } - - // slow case - __ bind(slow_case); - __ pop(rcx); // restore stack pointer to what it was when we came in. - __ bind(slow_case_no_pop); - __ get_constant_pool(rax); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), rax, rdx); - - // continue - __ bind(done); -} - - -void TemplateTable::newarray() { - transition(itos, atos); - __ push_i(rax); // make sure everything is on the stack - __ load_unsigned_byte(rdx, at_bcp(1)); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), rdx, rax); - __ pop_i(rdx); // discard size -} - - -void TemplateTable::anewarray() { - transition(itos, atos); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - __ get_constant_pool(rcx); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), rcx, rdx, rax); -} - - -void TemplateTable::arraylength() { - transition(atos, itos); - __ null_check(rax, arrayOopDesc::length_offset_in_bytes()); - __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes())); -} - - -void TemplateTable::checkcast() { - transition(atos, atos); - Label done, is_null, ok_is_subtype, quicked, resolved; - __ testptr(rax, rax); // Object is in EAX - __ jcc(Assembler::zero, is_null); - - // Get cpool & tags index - __ get_cpool_and_tags(rcx, rdx); // ECX=cpool, EDX=tags array - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // EBX=index - // See if bytecode has already been quicked - __ cmpb(Address(rdx, rbx, Address::times_1, Array::base_offset_in_bytes()), JVM_CONSTANT_Class); - __ jcc(Assembler::equal, quicked); - - __ push(atos); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) ); - // vm_result_2 has metadata result - // borrow rdi from locals - __ get_thread(rdi); - __ get_vm_result_2(rax, rdi); - __ restore_locals(); - __ pop_ptr(rdx); - __ jmpb(resolved); - - // Get superklass in EAX and subklass in EBX - __ bind(quicked); - __ mov(rdx, rax); // Save object in EDX; EAX needed for subtype check - __ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(ConstantPool))); - - __ bind(resolved); - __ load_klass(rbx, rdx); - - // Generate subtype check. Blows ECX. Resets EDI. Object in EDX. - // Superklass in EAX. Subklass in EBX. - __ gen_subtype_check( rbx, ok_is_subtype ); - - // Come here on failure - __ push(rdx); - // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); - - // Come here on success - __ bind(ok_is_subtype); - __ mov(rax,rdx); // Restore object in EDX - - // Collect counts on whether this check-cast sees NULLs a lot or not. - if (ProfileInterpreter) { - __ jmp(done); - __ bind(is_null); - __ profile_null_seen(rcx); - } else { - __ bind(is_null); // same as 'done' - } - __ bind(done); -} - - -void TemplateTable::instanceof() { - transition(atos, itos); - Label done, is_null, ok_is_subtype, quicked, resolved; - __ testptr(rax, rax); - __ jcc(Assembler::zero, is_null); - - // Get cpool & tags index - __ get_cpool_and_tags(rcx, rdx); // ECX=cpool, EDX=tags array - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // EBX=index - // See if bytecode has already been quicked - __ cmpb(Address(rdx, rbx, Address::times_1, Array::base_offset_in_bytes()), JVM_CONSTANT_Class); - __ jcc(Assembler::equal, quicked); - - __ push(atos); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) ); - // vm_result_2 has metadata result - // borrow rdi from locals - __ get_thread(rdi); - __ get_vm_result_2(rax, rdi); - __ restore_locals(); - __ pop_ptr(rdx); - __ load_klass(rdx, rdx); - __ jmp(resolved); - - // Get superklass in EAX and subklass in EDX - __ bind(quicked); - __ load_klass(rdx, rax); - __ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(ConstantPool))); - - __ bind(resolved); - - // Generate subtype check. Blows ECX. Resets EDI. - // Superklass in EAX. Subklass in EDX. - __ gen_subtype_check( rdx, ok_is_subtype ); - - // Come here on failure - __ xorl(rax,rax); - __ jmpb(done); - // Come here on success - __ bind(ok_is_subtype); - __ movl(rax, 1); - - // Collect counts on whether this test sees NULLs a lot or not. - if (ProfileInterpreter) { - __ jmp(done); - __ bind(is_null); - __ profile_null_seen(rcx); - } else { - __ bind(is_null); // same as 'done' - } - __ bind(done); - // rax, = 0: obj == NULL or obj is not an instanceof the specified klass - // rax, = 1: obj != NULL and obj is an instanceof the specified klass -} - - -//---------------------------------------------------------------------------------------------------- -// Breakpoints -void TemplateTable::_breakpoint() { - - // Note: We get here even if we are single stepping.. - // jbug inists on setting breakpoints at every bytecode - // even if we are in single step mode. - - transition(vtos, vtos); - - // get the unpatched byte code - __ get_method(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::get_original_bytecode_at), rcx, rsi); - __ mov(rbx, rax); - - // post the breakpoint event - __ get_method(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), rcx, rsi); - - // complete the execution of original bytecode - __ dispatch_only_normal(vtos); -} - - -//---------------------------------------------------------------------------------------------------- -// Exceptions - -void TemplateTable::athrow() { - transition(atos, vtos); - __ null_check(rax); - __ jump(ExternalAddress(Interpreter::throw_exception_entry())); -} - - -//---------------------------------------------------------------------------------------------------- -// Synchronization -// -// Note: monitorenter & exit are symmetric routines; which is reflected -// in the assembly code structure as well -// -// Stack layout: -// -// [expressions ] <--- rsp = expression stack top -// .. -// [expressions ] -// [monitor entry] <--- monitor block top = expression stack bot -// .. -// [monitor entry] -// [frame data ] <--- monitor block bot -// ... -// [saved rbp, ] <--- rbp, - - -void TemplateTable::monitorenter() { - transition(atos, vtos); - - // check for NULL object - __ null_check(rax); - - const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); - const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); - const int entry_size = ( frame::interpreter_frame_monitor_size() * wordSize); - Label allocated; - - // initialize entry pointer - __ xorl(rdx, rdx); // points to free slot or NULL - - // find a free slot in the monitor block (result in rdx) - { Label entry, loop, exit; - __ movptr(rcx, monitor_block_top); // points to current entry, starting with top-most entry - - __ lea(rbx, monitor_block_bot); // points to word before bottom of monitor block - __ jmpb(entry); - - __ bind(loop); - __ cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used - __ cmovptr(Assembler::equal, rdx, rcx); // if not used then remember entry in rdx - __ cmpptr(rax, Address(rcx, BasicObjectLock::obj_offset_in_bytes())); // check if current entry is for same object - __ jccb(Assembler::equal, exit); // if same object then stop searching - __ addptr(rcx, entry_size); // otherwise advance to next entry - __ bind(entry); - __ cmpptr(rcx, rbx); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then check this entry - __ bind(exit); - } - - __ testptr(rdx, rdx); // check if a slot has been found - __ jccb(Assembler::notZero, allocated); // if found, continue with that one - - // allocate one if there's no free slot - { Label entry, loop; - // 1. compute new pointers // rsp: old expression stack top - __ movptr(rdx, monitor_block_bot); // rdx: old expression stack bottom - __ subptr(rsp, entry_size); // move expression stack top - __ subptr(rdx, entry_size); // move expression stack bottom - __ mov(rcx, rsp); // set start value for copy loop - __ movptr(monitor_block_bot, rdx); // set new monitor block top - __ jmp(entry); - // 2. move expression stack contents - __ bind(loop); - __ movptr(rbx, Address(rcx, entry_size)); // load expression stack word from old location - __ movptr(Address(rcx, 0), rbx); // and store it at new location - __ addptr(rcx, wordSize); // advance to next word - __ bind(entry); - __ cmpptr(rcx, rdx); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then copy next word - } - - // call run-time routine - // rdx: points to monitor entry - __ bind(allocated); - - // Increment bcp to point to the next bytecode, so exception handling for async. exceptions work correctly. - // The object has already been poped from the stack, so the expression stack looks correct. - __ increment(rsi); - - __ movptr(Address(rdx, BasicObjectLock::obj_offset_in_bytes()), rax); // store object - __ lock_object(rdx); - - // check to make sure this monitor doesn't cause stack overflow after locking - __ save_bcp(); // in case of exception - __ generate_stack_overflow_check(0); - - // The bcp has already been incremented. Just need to dispatch to next instruction. - __ dispatch_next(vtos); -} - - -void TemplateTable::monitorexit() { - transition(atos, vtos); - - // check for NULL object - __ null_check(rax); - - const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); - const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); - const int entry_size = ( frame::interpreter_frame_monitor_size() * wordSize); - Label found; - - // find matching slot - { Label entry, loop; - __ movptr(rdx, monitor_block_top); // points to current entry, starting with top-most entry - __ lea(rbx, monitor_block_bot); // points to word before bottom of monitor block - __ jmpb(entry); - - __ bind(loop); - __ cmpptr(rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); // check if current entry is for same object - __ jcc(Assembler::equal, found); // if same object then stop searching - __ addptr(rdx, entry_size); // otherwise advance to next entry - __ bind(entry); - __ cmpptr(rdx, rbx); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then check this entry - } - - // error handling. Unlocking was not block-structured - Label end; - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); - __ should_not_reach_here(); - - // call run-time routine - // rcx: points to monitor entry - __ bind(found); - __ push_ptr(rax); // make sure object is on stack (contract with oopMaps) - __ unlock_object(rdx); - __ pop_ptr(rax); // discard object - __ bind(end); -} - - -//---------------------------------------------------------------------------------------------------- -// Wide instructions - -void TemplateTable::wide() { - transition(vtos, vtos); - __ load_unsigned_byte(rbx, at_bcp(1)); - ExternalAddress wtable((address)Interpreter::_wentry_point); - __ jump(ArrayAddress(wtable, Address(noreg, rbx, Address::times_ptr))); - // Note: the rsi increment step is part of the individual wide bytecode implementations -} - - -//---------------------------------------------------------------------------------------------------- -// Multi arrays - -void TemplateTable::multianewarray() { - transition(vtos, atos); - __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions - // last dim is on top of stack; we want address of first one: - // first_addr = last_addr + (ndims - 1) * stackElementSize - 1*wordsize - // the latter wordSize to point to the beginning of the array. - __ lea( rax, Address(rsp, rax, Interpreter::stackElementScale(), -wordSize)); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), rax); // pass in rax, - __ load_unsigned_byte(rbx, at_bcp(3)); - __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); // get rid of counts -} - -#endif /* !CC_INTERP */ diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3741 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" -#include "interpreter/interp_masm.hpp" -#include "interpreter/templateTable.hpp" -#include "memory/universe.inline.hpp" -#include "oops/methodData.hpp" -#include "oops/objArrayKlass.hpp" -#include "oops/oop.inline.hpp" -#include "prims/methodHandles.hpp" -#include "runtime/sharedRuntime.hpp" -#include "runtime/stubRoutines.hpp" -#include "runtime/synchronizer.hpp" -#include "utilities/macros.hpp" - -#ifndef CC_INTERP - -#define __ _masm-> - -// Platform-dependent initialization - -void TemplateTable::pd_initialize() { - // No amd64 specific initialization -} - -// Address computation: local variables - -static inline Address iaddress(int n) { - return Address(r14, Interpreter::local_offset_in_bytes(n)); -} - -static inline Address laddress(int n) { - return iaddress(n + 1); -} - -static inline Address faddress(int n) { - return iaddress(n); -} - -static inline Address daddress(int n) { - return laddress(n); -} - -static inline Address aaddress(int n) { - return iaddress(n); -} - -static inline Address iaddress(Register r) { - return Address(r14, r, Address::times_8); -} - -static inline Address laddress(Register r) { - return Address(r14, r, Address::times_8, Interpreter::local_offset_in_bytes(1)); -} - -static inline Address faddress(Register r) { - return iaddress(r); -} - -static inline Address daddress(Register r) { - return laddress(r); -} - -static inline Address aaddress(Register r) { - return iaddress(r); -} - -static inline Address at_rsp() { - return Address(rsp, 0); -} - -// At top of Java expression stack which may be different than esp(). It -// isn't for category 1 objects. -static inline Address at_tos () { - return Address(rsp, Interpreter::expr_offset_in_bytes(0)); -} - -static inline Address at_tos_p1() { - return Address(rsp, Interpreter::expr_offset_in_bytes(1)); -} - -static inline Address at_tos_p2() { - return Address(rsp, Interpreter::expr_offset_in_bytes(2)); -} - -// Condition conversion -static Assembler::Condition j_not(TemplateTable::Condition cc) { - switch (cc) { - case TemplateTable::equal : return Assembler::notEqual; - case TemplateTable::not_equal : return Assembler::equal; - case TemplateTable::less : return Assembler::greaterEqual; - case TemplateTable::less_equal : return Assembler::greater; - case TemplateTable::greater : return Assembler::lessEqual; - case TemplateTable::greater_equal: return Assembler::less; - } - ShouldNotReachHere(); - return Assembler::zero; -} - - -// Miscelaneous helper routines -// Store an oop (or NULL) at the address described by obj. -// If val == noreg this means store a NULL - -static void do_oop_store(InterpreterMacroAssembler* _masm, - Address obj, - Register val, - BarrierSet::Name barrier, - bool precise) { - assert(val == noreg || val == rax, "parameter is just for looks"); - switch (barrier) { -#if INCLUDE_ALL_GCS - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging: - { - // flatten object address if needed - if (obj.index() == noreg && obj.disp() == 0) { - if (obj.base() != rdx) { - __ movq(rdx, obj.base()); - } - } else { - __ leaq(rdx, obj); - } - __ g1_write_barrier_pre(rdx /* obj */, - rbx /* pre_val */, - r15_thread /* thread */, - r8 /* tmp */, - val != noreg /* tosca_live */, - false /* expand_call */); - if (val == noreg) { - __ store_heap_oop_null(Address(rdx, 0)); - } else { - // G1 barrier needs uncompressed oop for region cross check. - Register new_val = val; - if (UseCompressedOops) { - new_val = rbx; - __ movptr(new_val, val); - } - __ store_heap_oop(Address(rdx, 0), val); - __ g1_write_barrier_post(rdx /* store_adr */, - new_val /* new_val */, - r15_thread /* thread */, - r8 /* tmp */, - rbx /* tmp2 */); - } - } - break; -#endif // INCLUDE_ALL_GCS - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: - { - if (val == noreg) { - __ store_heap_oop_null(obj); - } else { - __ store_heap_oop(obj, val); - // flatten object address if needed - if (!precise || (obj.index() == noreg && obj.disp() == 0)) { - __ store_check(obj.base()); - } else { - __ leaq(rdx, obj); - __ store_check(rdx); - } - } - } - break; - case BarrierSet::ModRef: - if (val == noreg) { - __ store_heap_oop_null(obj); - } else { - __ store_heap_oop(obj, val); - } - break; - default : - ShouldNotReachHere(); - - } -} - -Address TemplateTable::at_bcp(int offset) { - assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); - return Address(r13, offset); -} - -void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, - Register temp_reg, bool load_bc_into_bc_reg/*=true*/, - int byte_no) { - if (!RewriteBytecodes) return; - Label L_patch_done; - - switch (bc) { - case Bytecodes::_fast_aputfield: - case Bytecodes::_fast_bputfield: - case Bytecodes::_fast_cputfield: - case Bytecodes::_fast_dputfield: - case Bytecodes::_fast_fputfield: - case Bytecodes::_fast_iputfield: - case Bytecodes::_fast_lputfield: - case Bytecodes::_fast_sputfield: - { - // We skip bytecode quickening for putfield instructions when - // the put_code written to the constant pool cache is zero. - // This is required so that every execution of this instruction - // calls out to InterpreterRuntime::resolve_get_put to do - // additional, required work. - assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - assert(load_bc_into_bc_reg, "we use bc_reg as temp"); - __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1); - __ movl(bc_reg, bc); - __ cmpl(temp_reg, (int) 0); - __ jcc(Assembler::zero, L_patch_done); // don't patch - } - break; - default: - assert(byte_no == -1, "sanity"); - // the pair bytecodes have already done the load. - if (load_bc_into_bc_reg) { - __ movl(bc_reg, bc); - } - } - - if (JvmtiExport::can_post_breakpoint()) { - Label L_fast_patch; - // if a breakpoint is present we can't rewrite the stream directly - __ movzbl(temp_reg, at_bcp(0)); - __ cmpl(temp_reg, Bytecodes::_breakpoint); - __ jcc(Assembler::notEqual, L_fast_patch); - __ get_method(temp_reg); - // Let breakpoint table handling rewrite to quicker bytecode - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, r13, bc_reg); -#ifndef ASSERT - __ jmpb(L_patch_done); -#else - __ jmp(L_patch_done); -#endif - __ bind(L_fast_patch); - } - -#ifdef ASSERT - Label L_okay; - __ load_unsigned_byte(temp_reg, at_bcp(0)); - __ cmpl(temp_reg, (int) Bytecodes::java_code(bc)); - __ jcc(Assembler::equal, L_okay); - __ cmpl(temp_reg, bc_reg); - __ jcc(Assembler::equal, L_okay); - __ stop("patching the wrong bytecode"); - __ bind(L_okay); -#endif - - // patch bytecode - __ movb(at_bcp(0), bc_reg); - __ bind(L_patch_done); -} - - -// Individual instructions - -void TemplateTable::nop() { - transition(vtos, vtos); - // nothing to do -} - -void TemplateTable::shouldnotreachhere() { - transition(vtos, vtos); - __ stop("shouldnotreachhere bytecode"); -} - -void TemplateTable::aconst_null() { - transition(vtos, atos); - __ xorl(rax, rax); -} - -void TemplateTable::iconst(int value) { - transition(vtos, itos); - if (value == 0) { - __ xorl(rax, rax); - } else { - __ movl(rax, value); - } -} - -void TemplateTable::lconst(int value) { - transition(vtos, ltos); - if (value == 0) { - __ xorl(rax, rax); - } else { - __ movl(rax, value); - } -} - -void TemplateTable::fconst(int value) { - transition(vtos, ftos); - static float one = 1.0f, two = 2.0f; - switch (value) { - case 0: - __ xorps(xmm0, xmm0); - break; - case 1: - __ movflt(xmm0, ExternalAddress((address) &one)); - break; - case 2: - __ movflt(xmm0, ExternalAddress((address) &two)); - break; - default: - ShouldNotReachHere(); - break; - } -} - -void TemplateTable::dconst(int value) { - transition(vtos, dtos); - static double one = 1.0; - switch (value) { - case 0: - __ xorpd(xmm0, xmm0); - break; - case 1: - __ movdbl(xmm0, ExternalAddress((address) &one)); - break; - default: - ShouldNotReachHere(); - break; - } -} - -void TemplateTable::bipush() { - transition(vtos, itos); - __ load_signed_byte(rax, at_bcp(1)); -} - -void TemplateTable::sipush() { - transition(vtos, itos); - __ load_unsigned_short(rax, at_bcp(1)); - __ bswapl(rax); - __ sarl(rax, 16); -} - -void TemplateTable::ldc(bool wide) { - transition(vtos, vtos); - Label call_ldc, notFloat, notClass, Done; - - if (wide) { - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); - } else { - __ load_unsigned_byte(rbx, at_bcp(1)); - } - - __ get_cpool_and_tags(rcx, rax); - const int base_offset = ConstantPool::header_size() * wordSize; - const int tags_offset = Array::base_offset_in_bytes(); - - // get type - __ movzbl(rdx, Address(rax, rbx, Address::times_1, tags_offset)); - - // unresolved class - get the resolved class - __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass); - __ jccb(Assembler::equal, call_ldc); - - // unresolved class in error state - call into runtime to throw the error - // from the first resolution attempt - __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError); - __ jccb(Assembler::equal, call_ldc); - - // resolved class - need to call vm to get java mirror of the class - __ cmpl(rdx, JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, notClass); - - __ bind(call_ldc); - __ movl(c_rarg1, wide); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), c_rarg1); - __ push_ptr(rax); - __ verify_oop(rax); - __ jmp(Done); - - __ bind(notClass); - __ cmpl(rdx, JVM_CONSTANT_Float); - __ jccb(Assembler::notEqual, notFloat); - // ftos - __ movflt(xmm0, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_f(); - __ jmp(Done); - - __ bind(notFloat); -#ifdef ASSERT - { - Label L; - __ cmpl(rdx, JVM_CONSTANT_Integer); - __ jcc(Assembler::equal, L); - // String and Object are rewritten to fast_aldc - __ stop("unexpected tag type in ldc"); - __ bind(L); - } -#endif - // itos JVM_CONSTANT_Integer only - __ movl(rax, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_i(rax); - __ bind(Done); -} - -// Fast path for caching oop constants. -void TemplateTable::fast_aldc(bool wide) { - transition(vtos, atos); - - Register result = rax; - Register tmp = rdx; - int index_size = wide ? sizeof(u2) : sizeof(u1); - - Label resolved; - - // We are resolved if the resolved reference cache entry contains a - // non-null object (String, MethodType, etc.) - assert_different_registers(result, tmp); - __ get_cache_index_at_bcp(tmp, 1, index_size); - __ load_resolved_reference_at_index(result, tmp); - __ testl(result, result); - __ jcc(Assembler::notZero, resolved); - - address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); - - // first time invocation - must resolve first - __ movl(tmp, (int)bytecode()); - __ call_VM(result, entry, tmp); - - __ bind(resolved); - - if (VerifyOops) { - __ verify_oop(result); - } -} - -void TemplateTable::ldc2_w() { - transition(vtos, vtos); - Label Long, Done; - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); - - __ get_cpool_and_tags(rcx, rax); - const int base_offset = ConstantPool::header_size() * wordSize; - const int tags_offset = Array::base_offset_in_bytes(); - - // get type - __ cmpb(Address(rax, rbx, Address::times_1, tags_offset), - JVM_CONSTANT_Double); - __ jccb(Assembler::notEqual, Long); - // dtos - __ movdbl(xmm0, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_d(); - __ jmpb(Done); - - __ bind(Long); - // ltos - __ movq(rax, Address(rcx, rbx, Address::times_8, base_offset)); - __ push_l(); - - __ bind(Done); -} - -void TemplateTable::locals_index(Register reg, int offset) { - __ load_unsigned_byte(reg, at_bcp(offset)); - __ negptr(reg); -} - -void TemplateTable::iload() { - transition(vtos, itos); - if (RewriteFrequentPairs) { - Label rewrite, done; - const Register bc = c_rarg3; - assert(rbx != bc, "register damaged"); - - // get next byte - __ load_unsigned_byte(rbx, - at_bcp(Bytecodes::length_for(Bytecodes::_iload))); - // if _iload, wait to rewrite to iload2. We only want to rewrite the - // last two iloads in a pair. Comparing against fast_iload means that - // the next bytecode is neither an iload or a caload, and therefore - // an iload pair. - __ cmpl(rbx, Bytecodes::_iload); - __ jcc(Assembler::equal, done); - - __ cmpl(rbx, Bytecodes::_fast_iload); - __ movl(bc, Bytecodes::_fast_iload2); - __ jccb(Assembler::equal, rewrite); - - // if _caload, rewrite to fast_icaload - __ cmpl(rbx, Bytecodes::_caload); - __ movl(bc, Bytecodes::_fast_icaload); - __ jccb(Assembler::equal, rewrite); - - // rewrite so iload doesn't check again. - __ movl(bc, Bytecodes::_fast_iload); - - // rewrite - // bc: fast bytecode - __ bind(rewrite); - patch_bytecode(Bytecodes::_iload, bc, rbx, false); - __ bind(done); - } - - // Get the local value into tos - locals_index(rbx); - __ movl(rax, iaddress(rbx)); -} - -void TemplateTable::fast_iload2() { - transition(vtos, itos); - locals_index(rbx); - __ movl(rax, iaddress(rbx)); - __ push(itos); - locals_index(rbx, 3); - __ movl(rax, iaddress(rbx)); -} - -void TemplateTable::fast_iload() { - transition(vtos, itos); - locals_index(rbx); - __ movl(rax, iaddress(rbx)); -} - -void TemplateTable::lload() { - transition(vtos, ltos); - locals_index(rbx); - __ movq(rax, laddress(rbx)); -} - -void TemplateTable::fload() { - transition(vtos, ftos); - locals_index(rbx); - __ movflt(xmm0, faddress(rbx)); -} - -void TemplateTable::dload() { - transition(vtos, dtos); - locals_index(rbx); - __ movdbl(xmm0, daddress(rbx)); -} - -void TemplateTable::aload() { - transition(vtos, atos); - locals_index(rbx); - __ movptr(rax, aaddress(rbx)); -} - -void TemplateTable::locals_index_wide(Register reg) { - __ load_unsigned_short(reg, at_bcp(2)); - __ bswapl(reg); - __ shrl(reg, 16); - __ negptr(reg); -} - -void TemplateTable::wide_iload() { - transition(vtos, itos); - locals_index_wide(rbx); - __ movl(rax, iaddress(rbx)); -} - -void TemplateTable::wide_lload() { - transition(vtos, ltos); - locals_index_wide(rbx); - __ movq(rax, laddress(rbx)); -} - -void TemplateTable::wide_fload() { - transition(vtos, ftos); - locals_index_wide(rbx); - __ movflt(xmm0, faddress(rbx)); -} - -void TemplateTable::wide_dload() { - transition(vtos, dtos); - locals_index_wide(rbx); - __ movdbl(xmm0, daddress(rbx)); -} - -void TemplateTable::wide_aload() { - transition(vtos, atos); - locals_index_wide(rbx); - __ movptr(rax, aaddress(rbx)); -} - -void TemplateTable::index_check(Register array, Register index) { - // destroys rbx - // check array - __ null_check(array, arrayOopDesc::length_offset_in_bytes()); - // sign extend index for use by indexed load - __ movl2ptr(index, index); - // check index - __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes())); - if (index != rbx) { - // ??? convention: move aberrant index into ebx for exception message - assert(rbx != array, "different registers"); - __ movl(rbx, index); - } - __ jump_cc(Assembler::aboveEqual, - ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); -} - -void TemplateTable::iaload() { - transition(itos, itos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ movl(rax, Address(rdx, rax, - Address::times_4, - arrayOopDesc::base_offset_in_bytes(T_INT))); -} - -void TemplateTable::laload() { - transition(itos, ltos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ movq(rax, Address(rdx, rbx, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_LONG))); -} - -void TemplateTable::faload() { - transition(itos, ftos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ movflt(xmm0, Address(rdx, rax, - Address::times_4, - arrayOopDesc::base_offset_in_bytes(T_FLOAT))); -} - -void TemplateTable::daload() { - transition(itos, dtos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ movdbl(xmm0, Address(rdx, rax, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); -} - -void TemplateTable::aaload() { - transition(itos, atos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ load_heap_oop(rax, Address(rdx, rax, - UseCompressedOops ? Address::times_4 : Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_OBJECT))); -} - -void TemplateTable::baload() { - transition(itos, itos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ load_signed_byte(rax, - Address(rdx, rax, - Address::times_1, - arrayOopDesc::base_offset_in_bytes(T_BYTE))); -} - -void TemplateTable::caload() { - transition(itos, itos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ load_unsigned_short(rax, - Address(rdx, rax, - Address::times_2, - arrayOopDesc::base_offset_in_bytes(T_CHAR))); -} - -// iload followed by caload frequent pair -void TemplateTable::fast_icaload() { - transition(vtos, itos); - // load index out of locals - locals_index(rbx); - __ movl(rax, iaddress(rbx)); - - // eax: index - // rdx: array - __ pop_ptr(rdx); - index_check(rdx, rax); // kills rbx - __ load_unsigned_short(rax, - Address(rdx, rax, - Address::times_2, - arrayOopDesc::base_offset_in_bytes(T_CHAR))); -} - -void TemplateTable::saload() { - transition(itos, itos); - __ pop_ptr(rdx); - // eax: index - // rdx: array - index_check(rdx, rax); // kills rbx - __ load_signed_short(rax, - Address(rdx, rax, - Address::times_2, - arrayOopDesc::base_offset_in_bytes(T_SHORT))); -} - -void TemplateTable::iload(int n) { - transition(vtos, itos); - __ movl(rax, iaddress(n)); -} - -void TemplateTable::lload(int n) { - transition(vtos, ltos); - __ movq(rax, laddress(n)); -} - -void TemplateTable::fload(int n) { - transition(vtos, ftos); - __ movflt(xmm0, faddress(n)); -} - -void TemplateTable::dload(int n) { - transition(vtos, dtos); - __ movdbl(xmm0, daddress(n)); -} - -void TemplateTable::aload(int n) { - transition(vtos, atos); - __ movptr(rax, aaddress(n)); -} - -void TemplateTable::aload_0() { - transition(vtos, atos); - // According to bytecode histograms, the pairs: - // - // _aload_0, _fast_igetfield - // _aload_0, _fast_agetfield - // _aload_0, _fast_fgetfield - // - // occur frequently. If RewriteFrequentPairs is set, the (slow) - // _aload_0 bytecode checks if the next bytecode is either - // _fast_igetfield, _fast_agetfield or _fast_fgetfield and then - // rewrites the current bytecode into a pair bytecode; otherwise it - // rewrites the current bytecode into _fast_aload_0 that doesn't do - // the pair check anymore. - // - // Note: If the next bytecode is _getfield, the rewrite must be - // delayed, otherwise we may miss an opportunity for a pair. - // - // Also rewrite frequent pairs - // aload_0, aload_1 - // aload_0, iload_1 - // These bytecodes with a small amount of code are most profitable - // to rewrite - if (RewriteFrequentPairs) { - Label rewrite, done; - const Register bc = c_rarg3; - assert(rbx != bc, "register damaged"); - // get next byte - __ load_unsigned_byte(rbx, - at_bcp(Bytecodes::length_for(Bytecodes::_aload_0))); - - // do actual aload_0 - aload(0); - - // if _getfield then wait with rewrite - __ cmpl(rbx, Bytecodes::_getfield); - __ jcc(Assembler::equal, done); - - // if _igetfield then reqrite to _fast_iaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_igetfield); - __ movl(bc, Bytecodes::_fast_iaccess_0); - __ jccb(Assembler::equal, rewrite); - - // if _agetfield then reqrite to _fast_aaccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_agetfield); - __ movl(bc, Bytecodes::_fast_aaccess_0); - __ jccb(Assembler::equal, rewrite); - - // if _fgetfield then reqrite to _fast_faccess_0 - assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); - __ cmpl(rbx, Bytecodes::_fast_fgetfield); - __ movl(bc, Bytecodes::_fast_faccess_0); - __ jccb(Assembler::equal, rewrite); - - // else rewrite to _fast_aload0 - assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == - Bytecodes::_aload_0, - "fix bytecode definition"); - __ movl(bc, Bytecodes::_fast_aload_0); - - // rewrite - // bc: fast bytecode - __ bind(rewrite); - patch_bytecode(Bytecodes::_aload_0, bc, rbx, false); - - __ bind(done); - } else { - aload(0); - } -} - -void TemplateTable::istore() { - transition(itos, vtos); - locals_index(rbx); - __ movl(iaddress(rbx), rax); -} - -void TemplateTable::lstore() { - transition(ltos, vtos); - locals_index(rbx); - __ movq(laddress(rbx), rax); -} - -void TemplateTable::fstore() { - transition(ftos, vtos); - locals_index(rbx); - __ movflt(faddress(rbx), xmm0); -} - -void TemplateTable::dstore() { - transition(dtos, vtos); - locals_index(rbx); - __ movdbl(daddress(rbx), xmm0); -} - -void TemplateTable::astore() { - transition(vtos, vtos); - __ pop_ptr(rax); - locals_index(rbx); - __ movptr(aaddress(rbx), rax); -} - -void TemplateTable::wide_istore() { - transition(vtos, vtos); - __ pop_i(); - locals_index_wide(rbx); - __ movl(iaddress(rbx), rax); -} - -void TemplateTable::wide_lstore() { - transition(vtos, vtos); - __ pop_l(); - locals_index_wide(rbx); - __ movq(laddress(rbx), rax); -} - -void TemplateTable::wide_fstore() { - transition(vtos, vtos); - __ pop_f(); - locals_index_wide(rbx); - __ movflt(faddress(rbx), xmm0); -} - -void TemplateTable::wide_dstore() { - transition(vtos, vtos); - __ pop_d(); - locals_index_wide(rbx); - __ movdbl(daddress(rbx), xmm0); -} - -void TemplateTable::wide_astore() { - transition(vtos, vtos); - __ pop_ptr(rax); - locals_index_wide(rbx); - __ movptr(aaddress(rbx), rax); -} - -void TemplateTable::iastore() { - transition(itos, vtos); - __ pop_i(rbx); - __ pop_ptr(rdx); - // eax: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movl(Address(rdx, rbx, - Address::times_4, - arrayOopDesc::base_offset_in_bytes(T_INT)), - rax); -} - -void TemplateTable::lastore() { - transition(ltos, vtos); - __ pop_i(rbx); - __ pop_ptr(rdx); - // rax: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movq(Address(rdx, rbx, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_LONG)), - rax); -} - -void TemplateTable::fastore() { - transition(ftos, vtos); - __ pop_i(rbx); - __ pop_ptr(rdx); - // xmm0: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movflt(Address(rdx, rbx, - Address::times_4, - arrayOopDesc::base_offset_in_bytes(T_FLOAT)), - xmm0); -} - -void TemplateTable::dastore() { - transition(dtos, vtos); - __ pop_i(rbx); - __ pop_ptr(rdx); - // xmm0: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movdbl(Address(rdx, rbx, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_DOUBLE)), - xmm0); -} - -void TemplateTable::aastore() { - Label is_null, ok_is_subtype, done; - transition(vtos, vtos); - // stack: ..., array, index, value - __ movptr(rax, at_tos()); // value - __ movl(rcx, at_tos_p1()); // index - __ movptr(rdx, at_tos_p2()); // array - - Address element_address(rdx, rcx, - UseCompressedOops? Address::times_4 : Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - - index_check(rdx, rcx); // kills rbx - // do array store check - check for NULL value first - __ testptr(rax, rax); - __ jcc(Assembler::zero, is_null); - - // Move subklass into rbx - __ load_klass(rbx, rax); - // Move superklass into rax - __ load_klass(rax, rdx); - __ movptr(rax, Address(rax, - ObjArrayKlass::element_klass_offset())); - // Compress array + index*oopSize + 12 into a single register. Frees rcx. - __ lea(rdx, element_address); - - // Generate subtype check. Blows rcx, rdi - // Superklass in rax. Subklass in rbx. - __ gen_subtype_check(rbx, ok_is_subtype); - - // Come here on failure - // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); - - // Come here on success - __ bind(ok_is_subtype); - - // Get the value we will store - __ movptr(rax, at_tos()); - // Now store using the appropriate barrier - do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true); - __ jmp(done); - - // Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx] - __ bind(is_null); - __ profile_null_seen(rbx); - - // Store a NULL - do_oop_store(_masm, element_address, noreg, _bs->kind(), true); - - // Pop stack arguments - __ bind(done); - __ addptr(rsp, 3 * Interpreter::stackElementSize); -} - -void TemplateTable::bastore() { - transition(itos, vtos); - __ pop_i(rbx); - __ pop_ptr(rdx); - // eax: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movb(Address(rdx, rbx, - Address::times_1, - arrayOopDesc::base_offset_in_bytes(T_BYTE)), - rax); -} - -void TemplateTable::castore() { - transition(itos, vtos); - __ pop_i(rbx); - __ pop_ptr(rdx); - // eax: value - // ebx: index - // rdx: array - index_check(rdx, rbx); // prefer index in ebx - __ movw(Address(rdx, rbx, - Address::times_2, - arrayOopDesc::base_offset_in_bytes(T_CHAR)), - rax); -} - -void TemplateTable::sastore() { - castore(); -} - -void TemplateTable::istore(int n) { - transition(itos, vtos); - __ movl(iaddress(n), rax); -} - -void TemplateTable::lstore(int n) { - transition(ltos, vtos); - __ movq(laddress(n), rax); -} - -void TemplateTable::fstore(int n) { - transition(ftos, vtos); - __ movflt(faddress(n), xmm0); -} - -void TemplateTable::dstore(int n) { - transition(dtos, vtos); - __ movdbl(daddress(n), xmm0); -} - -void TemplateTable::astore(int n) { - transition(vtos, vtos); - __ pop_ptr(rax); - __ movptr(aaddress(n), rax); -} - -void TemplateTable::pop() { - transition(vtos, vtos); - __ addptr(rsp, Interpreter::stackElementSize); -} - -void TemplateTable::pop2() { - transition(vtos, vtos); - __ addptr(rsp, 2 * Interpreter::stackElementSize); -} - -void TemplateTable::dup() { - transition(vtos, vtos); - __ load_ptr(0, rax); - __ push_ptr(rax); - // stack: ..., a, a -} - -void TemplateTable::dup_x1() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr( 0, rax); // load b - __ load_ptr( 1, rcx); // load a - __ store_ptr(1, rax); // store b - __ store_ptr(0, rcx); // store a - __ push_ptr(rax); // push b - // stack: ..., b, a, b -} - -void TemplateTable::dup_x2() { - transition(vtos, vtos); - // stack: ..., a, b, c - __ load_ptr( 0, rax); // load c - __ load_ptr( 2, rcx); // load a - __ store_ptr(2, rax); // store c in a - __ push_ptr(rax); // push c - // stack: ..., c, b, c, c - __ load_ptr( 2, rax); // load b - __ store_ptr(2, rcx); // store a in b - // stack: ..., c, a, c, c - __ store_ptr(1, rax); // store b in c - // stack: ..., c, a, b, c -} - -void TemplateTable::dup2() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr(1, rax); // load a - __ push_ptr(rax); // push a - __ load_ptr(1, rax); // load b - __ push_ptr(rax); // push b - // stack: ..., a, b, a, b -} - -void TemplateTable::dup2_x1() { - transition(vtos, vtos); - // stack: ..., a, b, c - __ load_ptr( 0, rcx); // load c - __ load_ptr( 1, rax); // load b - __ push_ptr(rax); // push b - __ push_ptr(rcx); // push c - // stack: ..., a, b, c, b, c - __ store_ptr(3, rcx); // store c in b - // stack: ..., a, c, c, b, c - __ load_ptr( 4, rcx); // load a - __ store_ptr(2, rcx); // store a in 2nd c - // stack: ..., a, c, a, b, c - __ store_ptr(4, rax); // store b in a - // stack: ..., b, c, a, b, c -} - -void TemplateTable::dup2_x2() { - transition(vtos, vtos); - // stack: ..., a, b, c, d - __ load_ptr( 0, rcx); // load d - __ load_ptr( 1, rax); // load c - __ push_ptr(rax); // push c - __ push_ptr(rcx); // push d - // stack: ..., a, b, c, d, c, d - __ load_ptr( 4, rax); // load b - __ store_ptr(2, rax); // store b in d - __ store_ptr(4, rcx); // store d in b - // stack: ..., a, d, c, b, c, d - __ load_ptr( 5, rcx); // load a - __ load_ptr( 3, rax); // load c - __ store_ptr(3, rcx); // store a in c - __ store_ptr(5, rax); // store c in a - // stack: ..., c, d, a, b, c, d -} - -void TemplateTable::swap() { - transition(vtos, vtos); - // stack: ..., a, b - __ load_ptr( 1, rcx); // load a - __ load_ptr( 0, rax); // load b - __ store_ptr(0, rcx); // store a in b - __ store_ptr(1, rax); // store b in a - // stack: ..., b, a -} - -void TemplateTable::iop2(Operation op) { - transition(itos, itos); - switch (op) { - case add : __ pop_i(rdx); __ addl (rax, rdx); break; - case sub : __ movl(rdx, rax); __ pop_i(rax); __ subl (rax, rdx); break; - case mul : __ pop_i(rdx); __ imull(rax, rdx); break; - case _and : __ pop_i(rdx); __ andl (rax, rdx); break; - case _or : __ pop_i(rdx); __ orl (rax, rdx); break; - case _xor : __ pop_i(rdx); __ xorl (rax, rdx); break; - case shl : __ movl(rcx, rax); __ pop_i(rax); __ shll (rax); break; - case shr : __ movl(rcx, rax); __ pop_i(rax); __ sarl (rax); break; - case ushr : __ movl(rcx, rax); __ pop_i(rax); __ shrl (rax); break; - default : ShouldNotReachHere(); - } -} - -void TemplateTable::lop2(Operation op) { - transition(ltos, ltos); - switch (op) { - case add : __ pop_l(rdx); __ addptr(rax, rdx); break; - case sub : __ mov(rdx, rax); __ pop_l(rax); __ subptr(rax, rdx); break; - case _and : __ pop_l(rdx); __ andptr(rax, rdx); break; - case _or : __ pop_l(rdx); __ orptr (rax, rdx); break; - case _xor : __ pop_l(rdx); __ xorptr(rax, rdx); break; - default : ShouldNotReachHere(); - } -} - -void TemplateTable::idiv() { - transition(itos, itos); - __ movl(rcx, rax); - __ pop_i(rax); - // Note: could xor eax and ecx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivl(rcx); -} - -void TemplateTable::irem() { - transition(itos, itos); - __ movl(rcx, rax); - __ pop_i(rax); - // Note: could xor eax and ecx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivl(rcx); - __ movl(rax, rdx); -} - -void TemplateTable::lmul() { - transition(ltos, ltos); - __ pop_l(rdx); - __ imulq(rax, rdx); -} - -void TemplateTable::ldiv() { - transition(ltos, ltos); - __ mov(rcx, rax); - __ pop_l(rax); - // generate explicit div0 check - __ testq(rcx, rcx); - __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); - // Note: could xor rax and rcx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivq(rcx); // kills rbx -} - -void TemplateTable::lrem() { - transition(ltos, ltos); - __ mov(rcx, rax); - __ pop_l(rax); - __ testq(rcx, rcx); - __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); - // Note: could xor rax and rcx and compare with (-1 ^ min_int). If - // they are not equal, one could do a normal division (no correction - // needed), which may speed up this implementation for the common case. - // (see also JVM spec., p.243 & p.271) - __ corrected_idivq(rcx); // kills rbx - __ mov(rax, rdx); -} - -void TemplateTable::lshl() { - transition(itos, ltos); - __ movl(rcx, rax); // get shift count - __ pop_l(rax); // get shift value - __ shlq(rax); -} - -void TemplateTable::lshr() { - transition(itos, ltos); - __ movl(rcx, rax); // get shift count - __ pop_l(rax); // get shift value - __ sarq(rax); -} - -void TemplateTable::lushr() { - transition(itos, ltos); - __ movl(rcx, rax); // get shift count - __ pop_l(rax); // get shift value - __ shrq(rax); -} - -void TemplateTable::fop2(Operation op) { - transition(ftos, ftos); - switch (op) { - case add: - __ addss(xmm0, at_rsp()); - __ addptr(rsp, Interpreter::stackElementSize); - break; - case sub: - __ movflt(xmm1, xmm0); - __ pop_f(xmm0); - __ subss(xmm0, xmm1); - break; - case mul: - __ mulss(xmm0, at_rsp()); - __ addptr(rsp, Interpreter::stackElementSize); - break; - case div: - __ movflt(xmm1, xmm0); - __ pop_f(xmm0); - __ divss(xmm0, xmm1); - break; - case rem: - __ movflt(xmm1, xmm0); - __ pop_f(xmm0); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::frem), 2); - break; - default: - ShouldNotReachHere(); - break; - } -} - -void TemplateTable::dop2(Operation op) { - transition(dtos, dtos); - switch (op) { - case add: - __ addsd(xmm0, at_rsp()); - __ addptr(rsp, 2 * Interpreter::stackElementSize); - break; - case sub: - __ movdbl(xmm1, xmm0); - __ pop_d(xmm0); - __ subsd(xmm0, xmm1); - break; - case mul: - __ mulsd(xmm0, at_rsp()); - __ addptr(rsp, 2 * Interpreter::stackElementSize); - break; - case div: - __ movdbl(xmm1, xmm0); - __ pop_d(xmm0); - __ divsd(xmm0, xmm1); - break; - case rem: - __ movdbl(xmm1, xmm0); - __ pop_d(xmm0); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::drem), 2); - break; - default: - ShouldNotReachHere(); - break; - } -} - -void TemplateTable::ineg() { - transition(itos, itos); - __ negl(rax); -} - -void TemplateTable::lneg() { - transition(ltos, ltos); - __ negq(rax); -} - -// Note: 'double' and 'long long' have 32-bits alignment on x86. -static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) { - // Use the expression (adr)&(~0xF) to provide 128-bits aligned address - // of 128-bits operands for SSE instructions. - jlong *operand = (jlong*)(((intptr_t)adr)&((intptr_t)(~0xF))); - // Store the value to a 128-bits operand. - operand[0] = lo; - operand[1] = hi; - return operand; -} - -// Buffer for 128-bits masks used by SSE instructions. -static jlong float_signflip_pool[2*2]; -static jlong double_signflip_pool[2*2]; - -void TemplateTable::fneg() { - transition(ftos, ftos); - static jlong *float_signflip = double_quadword(&float_signflip_pool[1], 0x8000000080000000, 0x8000000080000000); - __ xorps(xmm0, ExternalAddress((address) float_signflip)); -} - -void TemplateTable::dneg() { - transition(dtos, dtos); - static jlong *double_signflip = double_quadword(&double_signflip_pool[1], 0x8000000000000000, 0x8000000000000000); - __ xorpd(xmm0, ExternalAddress((address) double_signflip)); -} - -void TemplateTable::iinc() { - transition(vtos, vtos); - __ load_signed_byte(rdx, at_bcp(2)); // get constant - locals_index(rbx); - __ addl(iaddress(rbx), rdx); -} - -void TemplateTable::wide_iinc() { - transition(vtos, vtos); - __ movl(rdx, at_bcp(4)); // get constant - locals_index_wide(rbx); - __ bswapl(rdx); // swap bytes & sign-extend constant - __ sarl(rdx, 16); - __ addl(iaddress(rbx), rdx); - // Note: should probably use only one movl to get both - // the index and the constant -> fix this -} - -void TemplateTable::convert() { - // Checking -#ifdef ASSERT - { - TosState tos_in = ilgl; - TosState tos_out = ilgl; - switch (bytecode()) { - case Bytecodes::_i2l: // fall through - case Bytecodes::_i2f: // fall through - case Bytecodes::_i2d: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: tos_in = itos; break; - case Bytecodes::_l2i: // fall through - case Bytecodes::_l2f: // fall through - case Bytecodes::_l2d: tos_in = ltos; break; - case Bytecodes::_f2i: // fall through - case Bytecodes::_f2l: // fall through - case Bytecodes::_f2d: tos_in = ftos; break; - case Bytecodes::_d2i: // fall through - case Bytecodes::_d2l: // fall through - case Bytecodes::_d2f: tos_in = dtos; break; - default : ShouldNotReachHere(); - } - switch (bytecode()) { - case Bytecodes::_l2i: // fall through - case Bytecodes::_f2i: // fall through - case Bytecodes::_d2i: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: tos_out = itos; break; - case Bytecodes::_i2l: // fall through - case Bytecodes::_f2l: // fall through - case Bytecodes::_d2l: tos_out = ltos; break; - case Bytecodes::_i2f: // fall through - case Bytecodes::_l2f: // fall through - case Bytecodes::_d2f: tos_out = ftos; break; - case Bytecodes::_i2d: // fall through - case Bytecodes::_l2d: // fall through - case Bytecodes::_f2d: tos_out = dtos; break; - default : ShouldNotReachHere(); - } - transition(tos_in, tos_out); - } -#endif // ASSERT - - static const int64_t is_nan = 0x8000000000000000L; - - // Conversion - switch (bytecode()) { - case Bytecodes::_i2l: - __ movslq(rax, rax); - break; - case Bytecodes::_i2f: - __ cvtsi2ssl(xmm0, rax); - break; - case Bytecodes::_i2d: - __ cvtsi2sdl(xmm0, rax); - break; - case Bytecodes::_i2b: - __ movsbl(rax, rax); - break; - case Bytecodes::_i2c: - __ movzwl(rax, rax); - break; - case Bytecodes::_i2s: - __ movswl(rax, rax); - break; - case Bytecodes::_l2i: - __ movl(rax, rax); - break; - case Bytecodes::_l2f: - __ cvtsi2ssq(xmm0, rax); - break; - case Bytecodes::_l2d: - __ cvtsi2sdq(xmm0, rax); - break; - case Bytecodes::_f2i: - { - Label L; - __ cvttss2sil(rax, xmm0); - __ cmpl(rax, 0x80000000); // NaN or overflow/underflow? - __ jcc(Assembler::notEqual, L); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); - __ bind(L); - } - break; - case Bytecodes::_f2l: - { - Label L; - __ cvttss2siq(rax, xmm0); - // NaN or overflow/underflow? - __ cmp64(rax, ExternalAddress((address) &is_nan)); - __ jcc(Assembler::notEqual, L); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); - __ bind(L); - } - break; - case Bytecodes::_f2d: - __ cvtss2sd(xmm0, xmm0); - break; - case Bytecodes::_d2i: - { - Label L; - __ cvttsd2sil(rax, xmm0); - __ cmpl(rax, 0x80000000); // NaN or overflow/underflow? - __ jcc(Assembler::notEqual, L); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 1); - __ bind(L); - } - break; - case Bytecodes::_d2l: - { - Label L; - __ cvttsd2siq(rax, xmm0); - // NaN or overflow/underflow? - __ cmp64(rax, ExternalAddress((address) &is_nan)); - __ jcc(Assembler::notEqual, L); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 1); - __ bind(L); - } - break; - case Bytecodes::_d2f: - __ cvtsd2ss(xmm0, xmm0); - break; - default: - ShouldNotReachHere(); - } -} - -void TemplateTable::lcmp() { - transition(ltos, itos); - Label done; - __ pop_l(rdx); - __ cmpq(rdx, rax); - __ movl(rax, -1); - __ jccb(Assembler::less, done); - __ setb(Assembler::notEqual, rax); - __ movzbl(rax, rax); - __ bind(done); -} - -void TemplateTable::float_cmp(bool is_float, int unordered_result) { - Label done; - if (is_float) { - // XXX get rid of pop here, use ... reg, mem32 - __ pop_f(xmm1); - __ ucomiss(xmm1, xmm0); - } else { - // XXX get rid of pop here, use ... reg, mem64 - __ pop_d(xmm1); - __ ucomisd(xmm1, xmm0); - } - if (unordered_result < 0) { - __ movl(rax, -1); - __ jccb(Assembler::parity, done); - __ jccb(Assembler::below, done); - __ setb(Assembler::notEqual, rdx); - __ movzbl(rax, rdx); - } else { - __ movl(rax, 1); - __ jccb(Assembler::parity, done); - __ jccb(Assembler::above, done); - __ movl(rax, 0); - __ jccb(Assembler::equal, done); - __ decrementl(rax); - } - __ bind(done); -} - -void TemplateTable::branch(bool is_jsr, bool is_wide) { - __ get_method(rcx); // rcx holds method - __ profile_taken_branch(rax, rbx); // rax holds updated MDP, rbx - // holds bumped taken count - - const ByteSize be_offset = MethodCounters::backedge_counter_offset() + - InvocationCounter::counter_offset(); - const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + - InvocationCounter::counter_offset(); - - // Load up edx with the branch displacement - if (is_wide) { - __ movl(rdx, at_bcp(1)); - } else { - __ load_signed_short(rdx, at_bcp(1)); - } - __ bswapl(rdx); - - if (!is_wide) { - __ sarl(rdx, 16); - } - __ movl2ptr(rdx, rdx); - - // Handle all the JSR stuff here, then exit. - // It's much shorter and cleaner than intermingling with the non-JSR - // normal-branch stuff occurring below. - if (is_jsr) { - // Pre-load the next target bytecode into rbx - __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1, 0)); - - // compute return address as bci in rax - __ lea(rax, at_bcp((is_wide ? 5 : 3) - - in_bytes(ConstMethod::codes_offset()))); - __ subptr(rax, Address(rcx, Method::const_offset())); - // Adjust the bcp in r13 by the displacement in rdx - __ addptr(r13, rdx); - // jsr returns atos that is not an oop - __ push_i(rax); - __ dispatch_only(vtos); - return; - } - - // Normal (non-jsr) branch handling - - // Adjust the bcp in r13 by the displacement in rdx - __ addptr(r13, rdx); - - assert(UseLoopCounter || !UseOnStackReplacement, - "on-stack-replacement requires loop counters"); - Label backedge_counter_overflow; - Label profile_method; - Label dispatch; - if (UseLoopCounter) { - // increment backedge counter for backward branches - // rax: MDO - // ebx: MDO bumped taken-count - // rcx: method - // rdx: target offset - // r13: target bcp - // r14: locals pointer - __ testl(rdx, rdx); // check if forward or backward branch - __ jcc(Assembler::positive, dispatch); // count only if backward branch - - // check if MethodCounters exists - Label has_counters; - __ movptr(rax, Address(rcx, Method::method_counters_offset())); - __ testptr(rax, rax); - __ jcc(Assembler::notZero, has_counters); - __ push(rdx); - __ push(rcx); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), - rcx); - __ pop(rcx); - __ pop(rdx); - __ movptr(rax, Address(rcx, Method::method_counters_offset())); - __ jcc(Assembler::zero, dispatch); - __ bind(has_counters); - - if (TieredCompilation) { - Label no_mdo; - int increment = InvocationCounter::count_increment; - if (ProfileInterpreter) { - // Are we profiling? - __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset()))); - __ testptr(rbx, rbx); - __ jccb(Assembler::zero, no_mdo); - // Increment the MDO backedge counter - const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) + - in_bytes(InvocationCounter::counter_offset())); - const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset())); - __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, - rax, false, Assembler::zero, &backedge_counter_overflow); - __ jmp(dispatch); - } - __ bind(no_mdo); - // Increment backedge counter in MethodCounters* - __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); - __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask, - rax, false, Assembler::zero, &backedge_counter_overflow); - } else { // not TieredCompilation - // increment counter - __ movptr(rcx, Address(rcx, Method::method_counters_offset())); - __ movl(rax, Address(rcx, be_offset)); // load backedge counter - __ incrementl(rax, InvocationCounter::count_increment); // increment counter - __ movl(Address(rcx, be_offset), rax); // store counter - - __ movl(rax, Address(rcx, inv_offset)); // load invocation counter - - __ andl(rax, InvocationCounter::count_mask_value); // and the status bits - __ addl(rax, Address(rcx, be_offset)); // add both counters - - if (ProfileInterpreter) { - // Test to see if we should create a method data oop - __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); - __ jcc(Assembler::less, dispatch); - - // if no method data exists, go to profile method - __ test_method_data_pointer(rax, profile_method); - - if (UseOnStackReplacement) { - // check for overflow against ebx which is the MDO taken count - __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); - __ jcc(Assembler::below, dispatch); - - // When ProfileInterpreter is on, the backedge_count comes - // from the MethodData*, which value does not get reset on - // the call to frequency_counter_overflow(). To avoid - // excessive calls to the overflow routine while the method is - // being compiled, add a second test to make sure the overflow - // function is called only once every overflow_frequency. - const int overflow_frequency = 1024; - __ andl(rbx, overflow_frequency - 1); - __ jcc(Assembler::zero, backedge_counter_overflow); - - } - } else { - if (UseOnStackReplacement) { - // check for overflow against eax, which is the sum of the - // counters - __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); - __ jcc(Assembler::aboveEqual, backedge_counter_overflow); - - } - } - } - __ bind(dispatch); - } - - // Pre-load the next target bytecode into rbx - __ load_unsigned_byte(rbx, Address(r13, 0)); - - // continue with the bytecode @ target - // eax: return bci for jsr's, unused otherwise - // ebx: target bytecode - // r13: target bcp - __ dispatch_only(vtos); - - if (UseLoopCounter) { - if (ProfileInterpreter) { - // Out-of-line code to allocate method data oop. - __ bind(profile_method); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); - __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode - __ set_method_data_pointer_for_bcp(); - __ jmp(dispatch); - } - - if (UseOnStackReplacement) { - // invocation counter overflow - __ bind(backedge_counter_overflow); - __ negptr(rdx); - __ addptr(rdx, r13); // branch bcp - // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::frequency_counter_overflow), - rdx); - __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode - - // rax: osr nmethod (osr ok) or NULL (osr not possible) - // ebx: target bytecode - // rdx: scratch - // r14: locals pointer - // r13: bcp - __ testptr(rax, rax); // test result - __ jcc(Assembler::zero, dispatch); // no osr if null - // nmethod may have been invalidated (VM may block upon call_VM return) - __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use); - __ jcc(Assembler::notEqual, dispatch); - - // We have the address of an on stack replacement routine in eax - // We need to prepare to execute the OSR method. First we must - // migrate the locals and monitors off of the stack. - - __ mov(r13, rax); // save the nmethod - - call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); - - // eax is OSR buffer, move it to expected parameter location - __ mov(j_rarg0, rax); - - // We use j_rarg definitions here so that registers don't conflict as parameter - // registers change across platforms as we are in the midst of a calling - // sequence to the OSR nmethod and we don't want collision. These are NOT parameters. - - const Register retaddr = j_rarg2; - const Register sender_sp = j_rarg1; - - // pop the interpreter frame - __ movptr(sender_sp, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp - __ leave(); // remove frame anchor - __ pop(retaddr); // get return address - __ mov(rsp, sender_sp); // set sp to sender sp - // Ensure compiled code always sees stack at proper alignment - __ andptr(rsp, -(StackAlignmentInBytes)); - - // unlike x86 we need no specialized return from compiled code - // to the interpreter or the call stub. - - // push the return address - __ push(retaddr); - - // and begin the OSR nmethod - __ jmp(Address(r13, nmethod::osr_entry_point_offset())); - } - } -} - - -void TemplateTable::if_0cmp(Condition cc) { - transition(itos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ testl(rax, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - -void TemplateTable::if_icmp(Condition cc) { - transition(itos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ pop_i(rdx); - __ cmpl(rdx, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - -void TemplateTable::if_nullcmp(Condition cc) { - transition(atos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ testptr(rax, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - -void TemplateTable::if_acmp(Condition cc) { - transition(atos, vtos); - // assume branch is more often taken than not (loops use backward branches) - Label not_taken; - __ pop_ptr(rdx); - __ cmpptr(rdx, rax); - __ jcc(j_not(cc), not_taken); - branch(false, false); - __ bind(not_taken); - __ profile_not_taken_branch(rax); -} - -void TemplateTable::ret() { - transition(vtos, vtos); - locals_index(rbx); - __ movslq(rbx, iaddress(rbx)); // get return bci, compute return bcp - __ profile_ret(rbx, rcx); - __ get_method(rax); - __ movptr(r13, Address(rax, Method::const_offset())); - __ lea(r13, Address(r13, rbx, Address::times_1, - ConstMethod::codes_offset())); - __ dispatch_next(vtos); -} - -void TemplateTable::wide_ret() { - transition(vtos, vtos); - locals_index_wide(rbx); - __ movptr(rbx, aaddress(rbx)); // get return bci, compute return bcp - __ profile_ret(rbx, rcx); - __ get_method(rax); - __ movptr(r13, Address(rax, Method::const_offset())); - __ lea(r13, Address(r13, rbx, Address::times_1, ConstMethod::codes_offset())); - __ dispatch_next(vtos); -} - -void TemplateTable::tableswitch() { - Label default_case, continue_execution; - transition(itos, vtos); - // align r13 - __ lea(rbx, at_bcp(BytesPerInt)); - __ andptr(rbx, -BytesPerInt); - // load lo & hi - __ movl(rcx, Address(rbx, BytesPerInt)); - __ movl(rdx, Address(rbx, 2 * BytesPerInt)); - __ bswapl(rcx); - __ bswapl(rdx); - // check against lo & hi - __ cmpl(rax, rcx); - __ jcc(Assembler::less, default_case); - __ cmpl(rax, rdx); - __ jcc(Assembler::greater, default_case); - // lookup dispatch offset - __ subl(rax, rcx); - __ movl(rdx, Address(rbx, rax, Address::times_4, 3 * BytesPerInt)); - __ profile_switch_case(rax, rbx, rcx); - // continue execution - __ bind(continue_execution); - __ bswapl(rdx); - __ movl2ptr(rdx, rdx); - __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1)); - __ addptr(r13, rdx); - __ dispatch_only(vtos); - // handle default - __ bind(default_case); - __ profile_switch_default(rax); - __ movl(rdx, Address(rbx, 0)); - __ jmp(continue_execution); -} - -void TemplateTable::lookupswitch() { - transition(itos, itos); - __ stop("lookupswitch bytecode should have been rewritten"); -} - -void TemplateTable::fast_linearswitch() { - transition(itos, vtos); - Label loop_entry, loop, found, continue_execution; - // bswap rax so we can avoid bswapping the table entries - __ bswapl(rax); - // align r13 - __ lea(rbx, at_bcp(BytesPerInt)); // btw: should be able to get rid of - // this instruction (change offsets - // below) - __ andptr(rbx, -BytesPerInt); - // set counter - __ movl(rcx, Address(rbx, BytesPerInt)); - __ bswapl(rcx); - __ jmpb(loop_entry); - // table search - __ bind(loop); - __ cmpl(rax, Address(rbx, rcx, Address::times_8, 2 * BytesPerInt)); - __ jcc(Assembler::equal, found); - __ bind(loop_entry); - __ decrementl(rcx); - __ jcc(Assembler::greaterEqual, loop); - // default case - __ profile_switch_default(rax); - __ movl(rdx, Address(rbx, 0)); - __ jmp(continue_execution); - // entry found -> get offset - __ bind(found); - __ movl(rdx, Address(rbx, rcx, Address::times_8, 3 * BytesPerInt)); - __ profile_switch_case(rcx, rax, rbx); - // continue execution - __ bind(continue_execution); - __ bswapl(rdx); - __ movl2ptr(rdx, rdx); - __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1)); - __ addptr(r13, rdx); - __ dispatch_only(vtos); -} - -void TemplateTable::fast_binaryswitch() { - transition(itos, vtos); - // Implementation using the following core algorithm: - // - // int binary_search(int key, LookupswitchPair* array, int n) { - // // Binary search according to "Methodik des Programmierens" by - // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985. - // int i = 0; - // int j = n; - // while (i+1 < j) { - // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q) - // // with Q: for all i: 0 <= i < n: key < a[i] - // // where a stands for the array and assuming that the (inexisting) - // // element a[n] is infinitely big. - // int h = (i + j) >> 1; - // // i < h < j - // if (key < array[h].fast_match()) { - // j = h; - // } else { - // i = h; - // } - // } - // // R: a[i] <= key < a[i+1] or Q - // // (i.e., if key is within array, i is the correct index) - // return i; - // } - - // Register allocation - const Register key = rax; // already set (tosca) - const Register array = rbx; - const Register i = rcx; - const Register j = rdx; - const Register h = rdi; - const Register temp = rsi; - - // Find array start - __ lea(array, at_bcp(3 * BytesPerInt)); // btw: should be able to - // get rid of this - // instruction (change - // offsets below) - __ andptr(array, -BytesPerInt); - - // Initialize i & j - __ xorl(i, i); // i = 0; - __ movl(j, Address(array, -BytesPerInt)); // j = length(array); - - // Convert j into native byteordering - __ bswapl(j); - - // And start - Label entry; - __ jmp(entry); - - // binary search loop - { - Label loop; - __ bind(loop); - // int h = (i + j) >> 1; - __ leal(h, Address(i, j, Address::times_1)); // h = i + j; - __ sarl(h, 1); // h = (i + j) >> 1; - // if (key < array[h].fast_match()) { - // j = h; - // } else { - // i = h; - // } - // Convert array[h].match to native byte-ordering before compare - __ movl(temp, Address(array, h, Address::times_8)); - __ bswapl(temp); - __ cmpl(key, temp); - // j = h if (key < array[h].fast_match()) - __ cmovl(Assembler::less, j, h); - // i = h if (key >= array[h].fast_match()) - __ cmovl(Assembler::greaterEqual, i, h); - // while (i+1 < j) - __ bind(entry); - __ leal(h, Address(i, 1)); // i+1 - __ cmpl(h, j); // i+1 < j - __ jcc(Assembler::less, loop); - } - - // end of binary search, result index is i (must check again!) - Label default_case; - // Convert array[i].match to native byte-ordering before compare - __ movl(temp, Address(array, i, Address::times_8)); - __ bswapl(temp); - __ cmpl(key, temp); - __ jcc(Assembler::notEqual, default_case); - - // entry found -> j = offset - __ movl(j , Address(array, i, Address::times_8, BytesPerInt)); - __ profile_switch_case(i, key, array); - __ bswapl(j); - __ movl2ptr(j, j); - __ load_unsigned_byte(rbx, Address(r13, j, Address::times_1)); - __ addptr(r13, j); - __ dispatch_only(vtos); - - // default case -> j = default offset - __ bind(default_case); - __ profile_switch_default(i); - __ movl(j, Address(array, -2 * BytesPerInt)); - __ bswapl(j); - __ movl2ptr(j, j); - __ load_unsigned_byte(rbx, Address(r13, j, Address::times_1)); - __ addptr(r13, j); - __ dispatch_only(vtos); -} - - -void TemplateTable::_return(TosState state) { - transition(state, state); - assert(_desc->calls_vm(), - "inconsistent calls_vm information"); // call in remove_activation - - if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { - assert(state == vtos, "only valid state"); - __ movptr(c_rarg1, aaddress(0)); - __ load_klass(rdi, c_rarg1); - __ movl(rdi, Address(rdi, Klass::access_flags_offset())); - __ testl(rdi, JVM_ACC_HAS_FINALIZER); - Label skip_register_finalizer; - __ jcc(Assembler::zero, skip_register_finalizer); - - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), c_rarg1); - - __ bind(skip_register_finalizer); - } - - __ remove_activation(state, r13); - __ jmp(r13); -} - -// ---------------------------------------------------------------------------- -// Volatile variables demand their effects be made known to all CPU's -// in order. Store buffers on most chips allow reads & writes to -// reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode -// without some kind of memory barrier (i.e., it's not sufficient that -// the interpreter does not reorder volatile references, the hardware -// also must not reorder them). -// -// According to the new Java Memory Model (JMM): -// (1) All volatiles are serialized wrt to each other. ALSO reads & -// writes act as aquire & release, so: -// (2) A read cannot let unrelated NON-volatile memory refs that -// happen after the read float up to before the read. It's OK for -// non-volatile memory refs that happen before the volatile read to -// float down below it. -// (3) Similar a volatile write cannot let unrelated NON-volatile -// memory refs that happen BEFORE the write float down to after the -// write. It's OK for non-volatile memory refs that happen after the -// volatile write to float up before it. -// -// We only put in barriers around volatile refs (they are expensive), -// not _between_ memory refs (that would require us to track the -// flavor of the previous memory refs). Requirements (2) and (3) -// require some barriers before volatile stores and after volatile -// loads. These nearly cover requirement (1) but miss the -// volatile-store-volatile-load case. This final case is placed after -// volatile-stores although it could just as well go before -// volatile-loads. -void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits - order_constraint) { - // Helper function to insert a is-volatile test and memory barrier - if (os::is_MP()) { // Not needed on single CPU - __ membar(order_constraint); - } -} - -void TemplateTable::resolve_cache_and_index(int byte_no, - Register Rcache, - Register index, - size_t index_size) { - const Register temp = rbx; - assert_different_registers(Rcache, index, temp); - - Label resolved; - assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size); - __ cmpl(temp, (int) bytecode()); // have we resolved this bytecode? - __ jcc(Assembler::equal, resolved); - - // resolve first time through - address entry; - switch (bytecode()) { - case Bytecodes::_getstatic: - case Bytecodes::_putstatic: - case Bytecodes::_getfield: - case Bytecodes::_putfield: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); - break; - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: - case Bytecodes::_invokestatic: - case Bytecodes::_invokeinterface: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); - break; - case Bytecodes::_invokehandle: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); - break; - case Bytecodes::_invokedynamic: - entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); - break; - default: - fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); - break; - } - __ movl(temp, (int) bytecode()); - __ call_VM(noreg, entry, temp); - - // Update registers with resolved info - __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); - __ bind(resolved); -} - -// The cache and index registers must be set before call -void TemplateTable::load_field_cp_cache_entry(Register obj, - Register cache, - Register index, - Register off, - Register flags, - bool is_static = false) { - assert_different_registers(cache, index, flags, off); - - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - // Field offset - __ movptr(off, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + - ConstantPoolCacheEntry::f2_offset()))); - // Flags - __ movl(flags, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + - ConstantPoolCacheEntry::flags_offset()))); - - // klass overwrite register - if (is_static) { - __ movptr(obj, Address(cache, index, Address::times_ptr, - in_bytes(cp_base_offset + - ConstantPoolCacheEntry::f1_offset()))); - const int mirror_offset = in_bytes(Klass::java_mirror_offset()); - __ movptr(obj, Address(obj, mirror_offset)); - } -} - -void TemplateTable::load_invoke_cp_cache_entry(int byte_no, - Register method, - Register itable_index, - Register flags, - bool is_invokevirtual, - bool is_invokevfinal, /*unused*/ - bool is_invokedynamic) { - // setup registers - const Register cache = rcx; - const Register index = rdx; - assert_different_registers(method, flags); - assert_different_registers(method, cache, index); - assert_different_registers(itable_index, flags); - assert_different_registers(itable_index, cache, index); - // determine constant pool cache field offsets - assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant"); - const int method_offset = in_bytes( - ConstantPoolCache::base_offset() + - ((byte_no == f2_byte) - ? ConstantPoolCacheEntry::f2_offset() - : ConstantPoolCacheEntry::f1_offset())); - const int flags_offset = in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::flags_offset()); - // access constant pool cache fields - const int index_offset = in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::f2_offset()); - - size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); - resolve_cache_and_index(byte_no, cache, index, index_size); - __ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); - - if (itable_index != noreg) { - // pick up itable or appendix index from f2 also: - __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset)); - } - __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); -} - -// Correct values of the cache and index registers are preserved. -void TemplateTable::jvmti_post_field_access(Register cache, Register index, - bool is_static, bool has_tos) { - // do the JVMTI work here to avoid disturbing the register state below - // We use c_rarg registers here because we want to use the register used in - // the call to the VM - if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we - // take the time to call into the VM. - Label L1; - assert_different_registers(cache, index, rax); - __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rax, rax); - __ jcc(Assembler::zero, L1); - - __ get_cache_and_index_at_bcp(c_rarg2, c_rarg3, 1); - - // cache entry pointer - __ addptr(c_rarg2, in_bytes(ConstantPoolCache::base_offset())); - __ shll(c_rarg3, LogBytesPerWord); - __ addptr(c_rarg2, c_rarg3); - if (is_static) { - __ xorl(c_rarg1, c_rarg1); // NULL object reference - } else { - __ movptr(c_rarg1, at_tos()); // get object pointer without popping it - __ verify_oop(c_rarg1); - } - // c_rarg1: object pointer or NULL - // c_rarg2: cache entry pointer - // c_rarg3: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_access), - c_rarg1, c_rarg2, c_rarg3); - __ get_cache_and_index_at_bcp(cache, index, 1); - __ bind(L1); - } -} - -void TemplateTable::pop_and_check_object(Register r) { - __ pop_ptr(r); - __ null_check(r); // for field access must check obj. - __ verify_oop(r); -} - -void TemplateTable::getfield_or_static(int byte_no, bool is_static) { - transition(vtos, vtos); - - const Register cache = rcx; - const Register index = rdx; - const Register obj = c_rarg3; - const Register off = rbx; - const Register flags = rax; - const Register bc = c_rarg3; // uses same reg as obj, so don't mix them - - resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); - jvmti_post_field_access(cache, index, is_static, false); - load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - - if (!is_static) { - // obj is on the stack - pop_and_check_object(obj); - } - - const Address field(obj, off, Address::times_1); - - Label Done, notByte, notInt, notShort, notChar, - notLong, notFloat, notObj, notDouble; - - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask edx after the above shift - assert(btos == 0, "change code, btos != 0"); - - __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); - __ jcc(Assembler::notZero, notByte); - // btos - __ load_signed_byte(rax, field); - __ push(btos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notByte); - __ cmpl(flags, atos); - __ jcc(Assembler::notEqual, notObj); - // atos - __ load_heap_oop(rax, field); - __ push(atos); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notObj); - __ cmpl(flags, itos); - __ jcc(Assembler::notEqual, notInt); - // itos - __ movl(rax, field); - __ push(itos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notInt); - __ cmpl(flags, ctos); - __ jcc(Assembler::notEqual, notChar); - // ctos - __ load_unsigned_short(rax, field); - __ push(ctos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notChar); - __ cmpl(flags, stos); - __ jcc(Assembler::notEqual, notShort); - // stos - __ load_signed_short(rax, field); - __ push(stos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notShort); - __ cmpl(flags, ltos); - __ jcc(Assembler::notEqual, notLong); - // ltos - __ movq(rax, field); - __ push(ltos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notLong); - __ cmpl(flags, ftos); - __ jcc(Assembler::notEqual, notFloat); - // ftos - __ movflt(xmm0, field); - __ push(ftos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx); - } - __ jmp(Done); - - __ bind(notFloat); -#ifdef ASSERT - __ cmpl(flags, dtos); - __ jcc(Assembler::notEqual, notDouble); -#endif - // dtos - __ movdbl(xmm0, field); - __ push(dtos); - // Rewrite bytecode to be faster - if (!is_static) { - patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx); - } -#ifdef ASSERT - __ jmp(Done); - - __ bind(notDouble); - __ stop("Bad state"); -#endif - - __ bind(Done); - // [jk] not needed currently - // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadLoad | - // Assembler::LoadStore)); -} - - -void TemplateTable::getfield(int byte_no) { - getfield_or_static(byte_no, false); -} - -void TemplateTable::getstatic(int byte_no) { - getfield_or_static(byte_no, true); -} - -// The registers cache and index expected to be set before call. -// The function may destroy various registers, just not the cache and index registers. -void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { - transition(vtos, vtos); - - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - - if (JvmtiExport::can_post_field_modification()) { - // Check to see if a field modification watch has been set before - // we take the time to call into the VM. - Label L1; - assert_different_registers(cache, index, rax); - __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(rax, rax); - __ jcc(Assembler::zero, L1); - - __ get_cache_and_index_at_bcp(c_rarg2, rscratch1, 1); - - if (is_static) { - // Life is simple. Null out the object pointer. - __ xorl(c_rarg1, c_rarg1); - } else { - // Life is harder. The stack holds the value on top, followed by - // the object. We don't know the size of the value, though; it - // could be one or two words depending on its type. As a result, - // we must find the type to determine where the object is. - __ movl(c_rarg3, Address(c_rarg2, rscratch1, - Address::times_8, - in_bytes(cp_base_offset + - ConstantPoolCacheEntry::flags_offset()))); - __ shrl(c_rarg3, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask rcx after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - __ movptr(c_rarg1, at_tos_p1()); // initially assume a one word jvalue - __ cmpl(c_rarg3, ltos); - __ cmovptr(Assembler::equal, - c_rarg1, at_tos_p2()); // ltos (two word jvalue) - __ cmpl(c_rarg3, dtos); - __ cmovptr(Assembler::equal, - c_rarg1, at_tos_p2()); // dtos (two word jvalue) - } - // cache entry pointer - __ addptr(c_rarg2, in_bytes(cp_base_offset)); - __ shll(rscratch1, LogBytesPerWord); - __ addptr(c_rarg2, rscratch1); - // object (tos) - __ mov(c_rarg3, rsp); - // c_rarg1: object pointer set up above (NULL if static) - // c_rarg2: cache entry pointer - // c_rarg3: jvalue object on the stack - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_modification), - c_rarg1, c_rarg2, c_rarg3); - __ get_cache_and_index_at_bcp(cache, index, 1); - __ bind(L1); - } -} - -void TemplateTable::putfield_or_static(int byte_no, bool is_static) { - transition(vtos, vtos); - - const Register cache = rcx; - const Register index = rdx; - const Register obj = rcx; - const Register off = rbx; - const Register flags = rax; - const Register bc = c_rarg3; - - resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); - jvmti_post_field_mod(cache, index, is_static); - load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); - - // [jk] not needed currently - // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore | - // Assembler::StoreStore)); - - Label notVolatile, Done; - __ movl(rdx, flags); - __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - __ andl(rdx, 0x1); - - // field address - const Address field(obj, off, Address::times_1); - - Label notByte, notInt, notShort, notChar, - notLong, notFloat, notObj, notDouble; - - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - - assert(btos == 0, "change code, btos != 0"); - __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); - __ jcc(Assembler::notZero, notByte); - - // btos - { - __ pop(btos); - if (!is_static) pop_and_check_object(obj); - __ movb(field, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notByte); - __ cmpl(flags, atos); - __ jcc(Assembler::notEqual, notObj); - - // atos - { - __ pop(atos); - if (!is_static) pop_and_check_object(obj); - // Store into the field - do_oop_store(_masm, field, rax, _bs->kind(), false); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notObj); - __ cmpl(flags, itos); - __ jcc(Assembler::notEqual, notInt); - - // itos - { - __ pop(itos); - if (!is_static) pop_and_check_object(obj); - __ movl(field, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notInt); - __ cmpl(flags, ctos); - __ jcc(Assembler::notEqual, notChar); - - // ctos - { - __ pop(ctos); - if (!is_static) pop_and_check_object(obj); - __ movw(field, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notChar); - __ cmpl(flags, stos); - __ jcc(Assembler::notEqual, notShort); - - // stos - { - __ pop(stos); - if (!is_static) pop_and_check_object(obj); - __ movw(field, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notShort); - __ cmpl(flags, ltos); - __ jcc(Assembler::notEqual, notLong); - - // ltos - { - __ pop(ltos); - if (!is_static) pop_and_check_object(obj); - __ movq(field, rax); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notLong); - __ cmpl(flags, ftos); - __ jcc(Assembler::notEqual, notFloat); - - // ftos - { - __ pop(ftos); - if (!is_static) pop_and_check_object(obj); - __ movflt(field, xmm0); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - } - - __ bind(notFloat); -#ifdef ASSERT - __ cmpl(flags, dtos); - __ jcc(Assembler::notEqual, notDouble); -#endif - - // dtos - { - __ pop(dtos); - if (!is_static) pop_and_check_object(obj); - __ movdbl(field, xmm0); - if (!is_static) { - patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no); - } - } - -#ifdef ASSERT - __ jmp(Done); - - __ bind(notDouble); - __ stop("Bad state"); -#endif - - __ bind(Done); - - // Check for volatile store - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatile); - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - __ bind(notVolatile); -} - -void TemplateTable::putfield(int byte_no) { - putfield_or_static(byte_no, false); -} - -void TemplateTable::putstatic(int byte_no) { - putfield_or_static(byte_no, true); -} - -void TemplateTable::jvmti_post_fast_field_mod() { - if (JvmtiExport::can_post_field_modification()) { - // Check to see if a field modification watch has been set before - // we take the time to call into the VM. - Label L2; - __ mov32(c_rarg3, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(c_rarg3, c_rarg3); - __ jcc(Assembler::zero, L2); - __ pop_ptr(rbx); // copy the object pointer from tos - __ verify_oop(rbx); - __ push_ptr(rbx); // put the object pointer back on tos - // Save tos values before call_VM() clobbers them. Since we have - // to do it for every data type, we use the saved values as the - // jvalue object. - switch (bytecode()) { // load values into the jvalue object - case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; - case Bytecodes::_fast_bputfield: // fall through - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: // fall through - case Bytecodes::_fast_iputfield: __ push_i(rax); break; - case Bytecodes::_fast_dputfield: __ push_d(); break; - case Bytecodes::_fast_fputfield: __ push_f(); break; - case Bytecodes::_fast_lputfield: __ push_l(rax); break; - - default: - ShouldNotReachHere(); - } - __ mov(c_rarg3, rsp); // points to jvalue on the stack - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1); - __ verify_oop(rbx); - // rbx: object pointer copied above - // c_rarg2: cache entry pointer - // c_rarg3: jvalue object on the stack - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_modification), - rbx, c_rarg2, c_rarg3); - - switch (bytecode()) { // restore tos values - case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; - case Bytecodes::_fast_bputfield: // fall through - case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: // fall through - case Bytecodes::_fast_iputfield: __ pop_i(rax); break; - case Bytecodes::_fast_dputfield: __ pop_d(); break; - case Bytecodes::_fast_fputfield: __ pop_f(); break; - case Bytecodes::_fast_lputfield: __ pop_l(rax); break; - } - __ bind(L2); - } -} - -void TemplateTable::fast_storefield(TosState state) { - transition(state, vtos); - - ByteSize base = ConstantPoolCache::base_offset(); - - jvmti_post_fast_field_mod(); - - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rbx, 1); - - // test for volatile with rdx - __ movl(rdx, Address(rcx, rbx, Address::times_8, - in_bytes(base + - ConstantPoolCacheEntry::flags_offset()))); - - // replace index with field offset from cache entry - __ movptr(rbx, Address(rcx, rbx, Address::times_8, - in_bytes(base + ConstantPoolCacheEntry::f2_offset()))); - - // [jk] not needed currently - // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore | - // Assembler::StoreStore)); - - Label notVolatile; - __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - __ andl(rdx, 0x1); - - // Get object from stack - pop_and_check_object(rcx); - - // field address - const Address field(rcx, rbx, Address::times_1); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_aputfield: - do_oop_store(_masm, field, rax, _bs->kind(), false); - break; - case Bytecodes::_fast_lputfield: - __ movq(field, rax); - break; - case Bytecodes::_fast_iputfield: - __ movl(field, rax); - break; - case Bytecodes::_fast_bputfield: - __ movb(field, rax); - break; - case Bytecodes::_fast_sputfield: - // fall through - case Bytecodes::_fast_cputfield: - __ movw(field, rax); - break; - case Bytecodes::_fast_fputfield: - __ movflt(field, xmm0); - break; - case Bytecodes::_fast_dputfield: - __ movdbl(field, xmm0); - break; - default: - ShouldNotReachHere(); - } - - // Check for volatile store - __ testl(rdx, rdx); - __ jcc(Assembler::zero, notVolatile); - volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - __ bind(notVolatile); -} - - -void TemplateTable::fast_accessfield(TosState state) { - transition(atos, state); - - // Do the JVMTI work here to avoid disturbing the register state below - if (JvmtiExport::can_post_field_access()) { - // Check to see if a field access watch has been set before we - // take the time to call into the VM. - Label L1; - __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); - __ testl(rcx, rcx); - __ jcc(Assembler::zero, L1); - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1); - __ verify_oop(rax); - __ push_ptr(rax); // save object pointer before call_VM() clobbers it - __ mov(c_rarg1, rax); - // c_rarg1: object pointer copied above - // c_rarg2: cache entry pointer - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_field_access), - c_rarg1, c_rarg2); - __ pop_ptr(rax); // restore object pointer - __ bind(L1); - } - - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rbx, 1); - // replace index with field offset from cache entry - // [jk] not needed currently - // if (os::is_MP()) { - // __ movl(rdx, Address(rcx, rbx, Address::times_8, - // in_bytes(ConstantPoolCache::base_offset() + - // ConstantPoolCacheEntry::flags_offset()))); - // __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - // __ andl(rdx, 0x1); - // } - __ movptr(rbx, Address(rcx, rbx, Address::times_8, - in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::f2_offset()))); - - // rax: object - __ verify_oop(rax); - __ null_check(rax); - Address field(rax, rbx, Address::times_1); - - // access field - switch (bytecode()) { - case Bytecodes::_fast_agetfield: - __ load_heap_oop(rax, field); - __ verify_oop(rax); - break; - case Bytecodes::_fast_lgetfield: - __ movq(rax, field); - break; - case Bytecodes::_fast_igetfield: - __ movl(rax, field); - break; - case Bytecodes::_fast_bgetfield: - __ movsbl(rax, field); - break; - case Bytecodes::_fast_sgetfield: - __ load_signed_short(rax, field); - break; - case Bytecodes::_fast_cgetfield: - __ load_unsigned_short(rax, field); - break; - case Bytecodes::_fast_fgetfield: - __ movflt(xmm0, field); - break; - case Bytecodes::_fast_dgetfield: - __ movdbl(xmm0, field); - break; - default: - ShouldNotReachHere(); - } - // [jk] not needed currently - // if (os::is_MP()) { - // Label notVolatile; - // __ testl(rdx, rdx); - // __ jcc(Assembler::zero, notVolatile); - // __ membar(Assembler::LoadLoad); - // __ bind(notVolatile); - //}; -} - -void TemplateTable::fast_xaccess(TosState state) { - transition(vtos, state); - - // get receiver - __ movptr(rax, aaddress(0)); - // access constant pool cache - __ get_cache_and_index_at_bcp(rcx, rdx, 2); - __ movptr(rbx, - Address(rcx, rdx, Address::times_8, - in_bytes(ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::f2_offset()))); - // make sure exception is reported in correct bcp range (getfield is - // next instruction) - __ increment(r13); - __ null_check(rax); - switch (state) { - case itos: - __ movl(rax, Address(rax, rbx, Address::times_1)); - break; - case atos: - __ load_heap_oop(rax, Address(rax, rbx, Address::times_1)); - __ verify_oop(rax); - break; - case ftos: - __ movflt(xmm0, Address(rax, rbx, Address::times_1)); - break; - default: - ShouldNotReachHere(); - } - - // [jk] not needed currently - // if (os::is_MP()) { - // Label notVolatile; - // __ movl(rdx, Address(rcx, rdx, Address::times_8, - // in_bytes(ConstantPoolCache::base_offset() + - // ConstantPoolCacheEntry::flags_offset()))); - // __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); - // __ testl(rdx, 0x1); - // __ jcc(Assembler::zero, notVolatile); - // __ membar(Assembler::LoadLoad); - // __ bind(notVolatile); - // } - - __ decrement(r13); -} - - - -//----------------------------------------------------------------------------- -// Calls - -void TemplateTable::count_calls(Register method, Register temp) { - // implemented elsewhere - ShouldNotReachHere(); -} - -void TemplateTable::prepare_invoke(int byte_no, - Register method, // linked method (or i-klass) - Register index, // itable index, MethodType, etc. - Register recv, // if caller wants to see it - Register flags // if caller wants to test it - ) { - // determine flags - const Bytecodes::Code code = bytecode(); - const bool is_invokeinterface = code == Bytecodes::_invokeinterface; - const bool is_invokedynamic = code == Bytecodes::_invokedynamic; - const bool is_invokehandle = code == Bytecodes::_invokehandle; - const bool is_invokevirtual = code == Bytecodes::_invokevirtual; - const bool is_invokespecial = code == Bytecodes::_invokespecial; - const bool load_receiver = (recv != noreg); - const bool save_flags = (flags != noreg); - assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); - assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); - assert(flags == noreg || flags == rdx, ""); - assert(recv == noreg || recv == rcx, ""); - - // setup registers & access constant pool cache - if (recv == noreg) recv = rcx; - if (flags == noreg) flags = rdx; - assert_different_registers(method, index, recv, flags); - - // save 'interpreter return address' - __ save_bcp(); - - load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); - - // maybe push appendix to arguments (just before return address) - if (is_invokedynamic || is_invokehandle) { - Label L_no_push; - __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift)); - __ jcc(Assembler::zero, L_no_push); - // Push the appendix as a trailing parameter. - // This must be done before we get the receiver, - // since the parameter_size includes it. - __ push(rbx); - __ mov(rbx, index); - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); - __ load_resolved_reference_at_index(index, rbx); - __ pop(rbx); - __ push(index); // push appendix (MethodType, CallSite, etc.) - __ bind(L_no_push); - } - - // load receiver if needed (after appendix is pushed so parameter size is correct) - // Note: no return address pushed yet - if (load_receiver) { - __ movl(recv, flags); - __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask); - const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address - const int receiver_is_at_end = -1; // back off one slot to get receiver - Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end); - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } - - if (save_flags) { - __ movl(r13, flags); - } - - // compute return type - __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask flags after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - // load return address - { - const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); - ExternalAddress table(table_addr); - __ lea(rscratch1, table); - __ movptr(flags, Address(rscratch1, flags, Address::times_ptr)); - } - - // push return address - __ push(flags); - - // Restore flags value from the constant pool cache, and restore rsi - // for later null checks. r13 is the bytecode pointer - if (save_flags) { - __ movl(flags, r13); - __ restore_bcp(); - } -} - - -void TemplateTable::invokevirtual_helper(Register index, - Register recv, - Register flags) { - // Uses temporary registers rax, rdx - assert_different_registers(index, recv, rax, rdx); - assert(index == rbx, ""); - assert(recv == rcx, ""); - - // Test for an invoke of a final method - Label notFinal; - __ movl(rax, flags); - __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); - __ jcc(Assembler::zero, notFinal); - - const Register method = index; // method must be rbx - assert(method == rbx, - "Method* must be rbx for interpreter calling convention"); - - // do the call - the index is actually the method to call - // that is, f2 is a vtable index if !is_vfinal, else f2 is a Method* - - // It's final, need a null check here! - __ null_check(recv); - - // profile this call - __ profile_final_call(rax); - __ profile_arguments_type(rax, method, r13, true); - - __ jump_from_interpreted(method, rax); - - __ bind(notFinal); - - // get receiver klass - __ null_check(recv, oopDesc::klass_offset_in_bytes()); - __ load_klass(rax, recv); - - // profile this call - __ profile_virtual_call(rax, r14, rdx); - - // get target Method* & entry point - __ lookup_virtual_method(rax, index, method); - __ profile_arguments_type(rdx, method, r13, true); - __ jump_from_interpreted(method, rdx); -} - - -void TemplateTable::invokevirtual(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f2_byte, "use this argument"); - prepare_invoke(byte_no, - rbx, // method or vtable index - noreg, // unused itable index - rcx, rdx); // recv, flags - - // rbx: index - // rcx: receiver - // rdx: flags - - invokevirtual_helper(rbx, rcx, rdx); -} - - -void TemplateTable::invokespecial(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rbx, noreg, // get f1 Method* - rcx); // get receiver also for null check - __ verify_oop(rcx); - __ null_check(rcx); - // do the call - __ profile_call(rax); - __ profile_arguments_type(rax, rbx, r13, false); - __ jump_from_interpreted(rbx, rax); -} - - -void TemplateTable::invokestatic(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rbx); // get f1 Method* - // do the call - __ profile_call(rax); - __ profile_arguments_type(rax, rbx, r13, false); - __ jump_from_interpreted(rbx, rax); -} - -void TemplateTable::fast_invokevfinal(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f2_byte, "use this argument"); - __ stop("fast_invokevfinal not used on amd64"); -} - -void TemplateTable::invokeinterface(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index - rcx, rdx); // recv, flags - - // rax: interface klass (from f1) - // rbx: itable index (from f2) - // rcx: receiver - // rdx: flags - - // Special case of invokeinterface called for virtual method of - // java.lang.Object. See cpCacheOop.cpp for details. - // This code isn't produced by javac, but could be produced by - // another compliant java compiler. - Label notMethod; - __ movl(r14, rdx); - __ andl(r14, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); - __ jcc(Assembler::zero, notMethod); - - invokevirtual_helper(rbx, rcx, rdx); - __ bind(notMethod); - - // Get receiver klass into rdx - also a null check - __ restore_locals(); // restore r14 - __ null_check(rcx, oopDesc::klass_offset_in_bytes()); - __ load_klass(rdx, rcx); - - // profile this call - __ profile_virtual_call(rdx, r13, r14); - - Label no_such_interface, no_such_method; - - __ lookup_interface_method(// inputs: rec. class, interface, itable index - rdx, rax, rbx, - // outputs: method, scan temp. reg - rbx, r13, - no_such_interface); - - // rbx: Method* to call - // rcx: receiver - // Check for abstract method error - // Note: This should be done more efficiently via a throw_abstract_method_error - // interpreter entry point and a conditional jump to it in case of a null - // method. - __ testptr(rbx, rbx); - __ jcc(Assembler::zero, no_such_method); - - __ profile_arguments_type(rdx, rbx, r13, true); - - // do the call - // rcx: receiver - // rbx,: Method* - __ jump_from_interpreted(rbx, rdx); - __ should_not_reach_here(); - - // exception handling code follows... - // note: must restore interpreter registers to canonical - // state for exception handling to work correctly! - - __ bind(no_such_method); - // throw exception - __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); - - __ bind(no_such_interface); - // throw exception - __ pop(rbx); // pop return address (pushed by prepare_invoke) - __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_IncompatibleClassChangeError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); -} - - -void TemplateTable::invokehandle(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - const Register rbx_method = rbx; - const Register rax_mtype = rax; - const Register rcx_recv = rcx; - const Register rdx_flags = rdx; - - prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv); - __ verify_method_ptr(rbx_method); - __ verify_oop(rcx_recv); - __ null_check(rcx_recv); - - // rax: MethodType object (from cpool->resolved_references[f1], if necessary) - // rbx: MH.invokeExact_MT method (from f2) - - // Note: rax_mtype is already pushed (if necessary) by prepare_invoke - - // FIXME: profile the LambdaForm also - __ profile_final_call(rax); - __ profile_arguments_type(rdx, rbx_method, r13, true); - - __ jump_from_interpreted(rbx_method, rdx); -} - - -void TemplateTable::invokedynamic(int byte_no) { - transition(vtos, vtos); - assert(byte_no == f1_byte, "use this argument"); - - const Register rbx_method = rbx; - const Register rax_callsite = rax; - - prepare_invoke(byte_no, rbx_method, rax_callsite); - - // rax: CallSite object (from cpool->resolved_references[f1]) - // rbx: MH.linkToCallSite method (from f2) - - // Note: rax_callsite is already pushed by prepare_invoke - - // %%% should make a type profile for any invokedynamic that takes a ref argument - // profile this call - __ profile_call(r13); - __ profile_arguments_type(rdx, rbx_method, r13, false); - - __ verify_oop(rax_callsite); - - __ jump_from_interpreted(rbx_method, rdx); -} - - -//----------------------------------------------------------------------------- -// Allocation - -void TemplateTable::_new() { - transition(vtos, atos); - __ get_unsigned_2_byte_index_at_bcp(rdx, 1); - Label slow_case; - Label done; - Label initialize_header; - Label initialize_object; // including clearing the fields - Label allocate_shared; - - __ get_cpool_and_tags(rsi, rax); - // Make sure the class we're about to instantiate has been resolved. - // This is done before loading InstanceKlass to be consistent with the order - // how Constant Pool is updated (see ConstantPool::klass_at_put) - const int tags_offset = Array::base_offset_in_bytes(); - __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), - JVM_CONSTANT_Class); - __ jcc(Assembler::notEqual, slow_case); - - // get InstanceKlass - __ movptr(rsi, Address(rsi, rdx, - Address::times_8, sizeof(ConstantPool))); - - // make sure klass is initialized & doesn't have finalizer - // make sure klass is fully initialized - __ cmpb(Address(rsi, - InstanceKlass::init_state_offset()), - InstanceKlass::fully_initialized); - __ jcc(Assembler::notEqual, slow_case); - - // get instance_size in InstanceKlass (scaled to a count of bytes) - __ movl(rdx, - Address(rsi, - Klass::layout_helper_offset())); - // test to see if it has a finalizer or is malformed in some way - __ testl(rdx, Klass::_lh_instance_slow_path_bit); - __ jcc(Assembler::notZero, slow_case); - - // Allocate the instance - // 1) Try to allocate in the TLAB - // 2) if fail and the object is large allocate in the shared Eden - // 3) if the above fails (or is not applicable), go to a slow case - // (creates a new TLAB, etc.) - - const bool allow_shared_alloc = - Universe::heap()->supports_inline_contig_alloc(); - - if (UseTLAB) { - __ movptr(rax, Address(r15_thread, in_bytes(JavaThread::tlab_top_offset()))); - __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, Address(r15_thread, in_bytes(JavaThread::tlab_end_offset()))); - __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case); - __ movptr(Address(r15_thread, in_bytes(JavaThread::tlab_top_offset())), rbx); - if (ZeroTLAB) { - // the fields have been already cleared - __ jmp(initialize_header); - } else { - // initialize both the header and fields - __ jmp(initialize_object); - } - } - - // Allocation in the shared Eden, if allowed. - // - // rdx: instance size in bytes - if (allow_shared_alloc) { - __ bind(allocate_shared); - - ExternalAddress top((address)Universe::heap()->top_addr()); - ExternalAddress end((address)Universe::heap()->end_addr()); - - const Register RtopAddr = rscratch1; - const Register RendAddr = rscratch2; - - __ lea(RtopAddr, top); - __ lea(RendAddr, end); - __ movptr(rax, Address(RtopAddr, 0)); - - // For retries rax gets set by cmpxchgq - Label retry; - __ bind(retry); - __ lea(rbx, Address(rax, rdx, Address::times_1)); - __ cmpptr(rbx, Address(RendAddr, 0)); - __ jcc(Assembler::above, slow_case); - - // Compare rax with the top addr, and if still equal, store the new - // top addr in rbx at the address of the top addr pointer. Sets ZF if was - // equal, and clears it otherwise. Use lock prefix for atomicity on MPs. - // - // rax: object begin - // rbx: object end - // rdx: instance size in bytes - if (os::is_MP()) { - __ lock(); - } - __ cmpxchgptr(rbx, Address(RtopAddr, 0)); - - // if someone beat us on the allocation, try again, otherwise continue - __ jcc(Assembler::notEqual, retry); - - __ incr_allocated_bytes(r15_thread, rdx, 0); - } - - if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { - // The object is initialized before the header. If the object size is - // zero, go directly to the header initialization. - __ bind(initialize_object); - __ decrementl(rdx, sizeof(oopDesc)); - __ jcc(Assembler::zero, initialize_header); - - // Initialize object fields - __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) - __ shrl(rdx, LogBytesPerLong); // divide by oopSize to simplify the loop - { - Label loop; - __ bind(loop); - __ movq(Address(rax, rdx, Address::times_8, - sizeof(oopDesc) - oopSize), - rcx); - __ decrementl(rdx); - __ jcc(Assembler::notZero, loop); - } - - // initialize object header only. - __ bind(initialize_header); - if (UseBiasedLocking) { - __ movptr(rscratch1, Address(rsi, Klass::prototype_header_offset())); - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), rscratch1); - } else { - __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), - (intptr_t) markOopDesc::prototype()); // header (address 0x1) - } - __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) - __ store_klass_gap(rax, rcx); // zero klass gap for compressed oops - __ store_klass(rax, rsi); // store klass last - - { - SkipIfEqual skip(_masm, &DTraceAllocProbes, false); - // Trigger dtrace event for fastpath - __ push(atos); // save the return value - __ call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); - __ pop(atos); // restore the return value - - } - __ jmp(done); - } - - - // slow case - __ bind(slow_case); - __ get_constant_pool(c_rarg1); - __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), c_rarg1, c_rarg2); - __ verify_oop(rax); - - // continue - __ bind(done); -} - -void TemplateTable::newarray() { - transition(itos, atos); - __ load_unsigned_byte(c_rarg1, at_bcp(1)); - __ movl(c_rarg2, rax); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), - c_rarg1, c_rarg2); -} - -void TemplateTable::anewarray() { - transition(itos, atos); - __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); - __ get_constant_pool(c_rarg1); - __ movl(c_rarg3, rax); - call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), - c_rarg1, c_rarg2, c_rarg3); -} - -void TemplateTable::arraylength() { - transition(atos, itos); - __ null_check(rax, arrayOopDesc::length_offset_in_bytes()); - __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes())); -} - -void TemplateTable::checkcast() { - transition(atos, atos); - Label done, is_null, ok_is_subtype, quicked, resolved; - __ testptr(rax, rax); // object is in rax - __ jcc(Assembler::zero, is_null); - - // Get cpool & tags index - __ get_cpool_and_tags(rcx, rdx); // rcx=cpool, rdx=tags array - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // rbx=index - // See if bytecode has already been quicked - __ cmpb(Address(rdx, rbx, - Address::times_1, - Array::base_offset_in_bytes()), - JVM_CONSTANT_Class); - __ jcc(Assembler::equal, quicked); - __ push(atos); // save receiver for result, and for GC - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(rax, r15_thread); - __ pop_ptr(rdx); // restore receiver - __ jmpb(resolved); - - // Get superklass in rax and subklass in rbx - __ bind(quicked); - __ mov(rdx, rax); // Save object in rdx; rax needed for subtype check - __ movptr(rax, Address(rcx, rbx, - Address::times_8, sizeof(ConstantPool))); - - __ bind(resolved); - __ load_klass(rbx, rdx); - - // Generate subtype check. Blows rcx, rdi. Object in rdx. - // Superklass in rax. Subklass in rbx. - __ gen_subtype_check(rbx, ok_is_subtype); - - // Come here on failure - __ push_ptr(rdx); - // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); - - // Come here on success - __ bind(ok_is_subtype); - __ mov(rax, rdx); // Restore object in rdx - - // Collect counts on whether this check-cast sees NULLs a lot or not. - if (ProfileInterpreter) { - __ jmp(done); - __ bind(is_null); - __ profile_null_seen(rcx); - } else { - __ bind(is_null); // same as 'done' - } - __ bind(done); -} - -void TemplateTable::instanceof() { - transition(atos, itos); - Label done, is_null, ok_is_subtype, quicked, resolved; - __ testptr(rax, rax); - __ jcc(Assembler::zero, is_null); - - // Get cpool & tags index - __ get_cpool_and_tags(rcx, rdx); // rcx=cpool, rdx=tags array - __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // rbx=index - // See if bytecode has already been quicked - __ cmpb(Address(rdx, rbx, - Address::times_1, - Array::base_offset_in_bytes()), - JVM_CONSTANT_Class); - __ jcc(Assembler::equal, quicked); - - __ push(atos); // save receiver for result, and for GC - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(rax, r15_thread); - __ pop_ptr(rdx); // restore receiver - __ verify_oop(rdx); - __ load_klass(rdx, rdx); - __ jmpb(resolved); - - // Get superklass in rax and subklass in rdx - __ bind(quicked); - __ load_klass(rdx, rax); - __ movptr(rax, Address(rcx, rbx, - Address::times_8, sizeof(ConstantPool))); - - __ bind(resolved); - - // Generate subtype check. Blows rcx, rdi - // Superklass in rax. Subklass in rdx. - __ gen_subtype_check(rdx, ok_is_subtype); - - // Come here on failure - __ xorl(rax, rax); - __ jmpb(done); - // Come here on success - __ bind(ok_is_subtype); - __ movl(rax, 1); - - // Collect counts on whether this test sees NULLs a lot or not. - if (ProfileInterpreter) { - __ jmp(done); - __ bind(is_null); - __ profile_null_seen(rcx); - } else { - __ bind(is_null); // same as 'done' - } - __ bind(done); - // rax = 0: obj == NULL or obj is not an instanceof the specified klass - // rax = 1: obj != NULL and obj is an instanceof the specified klass -} - -//----------------------------------------------------------------------------- -// Breakpoints -void TemplateTable::_breakpoint() { - // Note: We get here even if we are single stepping.. - // jbug inists on setting breakpoints at every bytecode - // even if we are in single step mode. - - transition(vtos, vtos); - - // get the unpatched byte code - __ get_method(c_rarg1); - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::get_original_bytecode_at), - c_rarg1, r13); - __ mov(rbx, rax); - - // post the breakpoint event - __ get_method(c_rarg1); - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), - c_rarg1, r13); - - // complete the execution of original bytecode - __ dispatch_only_normal(vtos); -} - -//----------------------------------------------------------------------------- -// Exceptions - -void TemplateTable::athrow() { - transition(atos, vtos); - __ null_check(rax); - __ jump(ExternalAddress(Interpreter::throw_exception_entry())); -} - -//----------------------------------------------------------------------------- -// Synchronization -// -// Note: monitorenter & exit are symmetric routines; which is reflected -// in the assembly code structure as well -// -// Stack layout: -// -// [expressions ] <--- rsp = expression stack top -// .. -// [expressions ] -// [monitor entry] <--- monitor block top = expression stack bot -// .. -// [monitor entry] -// [frame data ] <--- monitor block bot -// ... -// [saved rbp ] <--- rbp -void TemplateTable::monitorenter() { - transition(atos, vtos); - - // check for NULL object - __ null_check(rax); - - const Address monitor_block_top( - rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); - const Address monitor_block_bot( - rbp, frame::interpreter_frame_initial_sp_offset * wordSize); - const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; - - Label allocated; - - // initialize entry pointer - __ xorl(c_rarg1, c_rarg1); // points to free slot or NULL - - // find a free slot in the monitor block (result in c_rarg1) - { - Label entry, loop, exit; - __ movptr(c_rarg3, monitor_block_top); // points to current entry, - // starting with top-most entry - __ lea(c_rarg2, monitor_block_bot); // points to word before bottom - // of monitor block - __ jmpb(entry); - - __ bind(loop); - // check if current entry is used - __ cmpptr(Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD); - // if not used then remember entry in c_rarg1 - __ cmov(Assembler::equal, c_rarg1, c_rarg3); - // check if current entry is for same object - __ cmpptr(rax, Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes())); - // if same object then stop searching - __ jccb(Assembler::equal, exit); - // otherwise advance to next entry - __ addptr(c_rarg3, entry_size); - __ bind(entry); - // check if bottom reached - __ cmpptr(c_rarg3, c_rarg2); - // if not at bottom then check this entry - __ jcc(Assembler::notEqual, loop); - __ bind(exit); - } - - __ testptr(c_rarg1, c_rarg1); // check if a slot has been found - __ jcc(Assembler::notZero, allocated); // if found, continue with that one - - // allocate one if there's no free slot - { - Label entry, loop; - // 1. compute new pointers // rsp: old expression stack top - __ movptr(c_rarg1, monitor_block_bot); // c_rarg1: old expression stack bottom - __ subptr(rsp, entry_size); // move expression stack top - __ subptr(c_rarg1, entry_size); // move expression stack bottom - __ mov(c_rarg3, rsp); // set start value for copy loop - __ movptr(monitor_block_bot, c_rarg1); // set new monitor block bottom - __ jmp(entry); - // 2. move expression stack contents - __ bind(loop); - __ movptr(c_rarg2, Address(c_rarg3, entry_size)); // load expression stack - // word from old location - __ movptr(Address(c_rarg3, 0), c_rarg2); // and store it at new location - __ addptr(c_rarg3, wordSize); // advance to next word - __ bind(entry); - __ cmpptr(c_rarg3, c_rarg1); // check if bottom reached - __ jcc(Assembler::notEqual, loop); // if not at bottom then - // copy next word - } - - // call run-time routine - // c_rarg1: points to monitor entry - __ bind(allocated); - - // Increment bcp to point to the next bytecode, so exception - // handling for async. exceptions work correctly. - // The object has already been poped from the stack, so the - // expression stack looks correct. - __ increment(r13); - - // store object - __ movptr(Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()), rax); - __ lock_object(c_rarg1); - - // check to make sure this monitor doesn't cause stack overflow after locking - __ save_bcp(); // in case of exception - __ generate_stack_overflow_check(0); - - // The bcp has already been incremented. Just need to dispatch to - // next instruction. - __ dispatch_next(vtos); -} - - -void TemplateTable::monitorexit() { - transition(atos, vtos); - - // check for NULL object - __ null_check(rax); - - const Address monitor_block_top( - rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); - const Address monitor_block_bot( - rbp, frame::interpreter_frame_initial_sp_offset * wordSize); - const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; - - Label found; - - // find matching slot - { - Label entry, loop; - __ movptr(c_rarg1, monitor_block_top); // points to current entry, - // starting with top-most entry - __ lea(c_rarg2, monitor_block_bot); // points to word before bottom - // of monitor block - __ jmpb(entry); - - __ bind(loop); - // check if current entry is for same object - __ cmpptr(rax, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); - // if same object then stop searching - __ jcc(Assembler::equal, found); - // otherwise advance to next entry - __ addptr(c_rarg1, entry_size); - __ bind(entry); - // check if bottom reached - __ cmpptr(c_rarg1, c_rarg2); - // if not at bottom then check this entry - __ jcc(Assembler::notEqual, loop); - } - - // error handling. Unlocking was not block-structured - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_illegal_monitor_state_exception)); - __ should_not_reach_here(); - - // call run-time routine - // rsi: points to monitor entry - __ bind(found); - __ push_ptr(rax); // make sure object is on stack (contract with oopMaps) - __ unlock_object(c_rarg1); - __ pop_ptr(rax); // discard object -} - - -// Wide instructions -void TemplateTable::wide() { - transition(vtos, vtos); - __ load_unsigned_byte(rbx, at_bcp(1)); - __ lea(rscratch1, ExternalAddress((address)Interpreter::_wentry_point)); - __ jmp(Address(rscratch1, rbx, Address::times_8)); - // Note: the r13 increment step is part of the individual wide - // bytecode implementations -} - - -// Multi arrays -void TemplateTable::multianewarray() { - transition(vtos, atos); - __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions - // last dim is on top of stack; we want address of first one: - // first_addr = last_addr + (ndims - 1) * wordSize - __ lea(c_rarg1, Address(rsp, rax, Address::times_8, -wordSize)); - call_VM(rax, - CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), - c_rarg1); - __ load_unsigned_byte(rbx, at_bcp(3)); - __ lea(rsp, Address(rsp, rbx, Address::times_8)); -} -#endif // !CC_INTERP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -227,31 +227,7 @@ #endif // Cpu architecture string -#if defined(ZERO) -static char cpu_arch[] = ZERO_LIBARCH; -#elif defined(IA64) -static char cpu_arch[] = "ia64"; -#elif defined(IA32) -static char cpu_arch[] = "i386"; -#elif defined(AMD64) -static char cpu_arch[] = "amd64"; -#elif defined(ARM) -static char cpu_arch[] = "arm"; -#elif defined(PPC32) -static char cpu_arch[] = "ppc"; -#elif defined(PPC64) -static char cpu_arch[] = "ppc64"; -#elif defined(SPARC) - #ifdef _LP64 -static char cpu_arch[] = "sparcv9"; - #else -static char cpu_arch[] = "sparc"; - #endif -#elif defined(AARCH64) -static char cpu_arch[] = "aarch64"; -#else - #error Add appropriate cpu_arch setting -#endif +static char cpu_arch[] = HOTSPOT_LIB_ARCH; // pid_t gettid() @@ -3296,7 +3272,7 @@ #ifndef ZERO large_page_size = IA32_ONLY(4 * M) AMD64_ONLY(2 * M) IA64_ONLY(256 * M) SPARC_ONLY(4 * M) - ARM_ONLY(2 * M) PPC_ONLY(4 * M) AARCH64_ONLY(2 * M); + ARM32_ONLY(2 * M) PPC_ONLY(4 * M) AARCH64_ONLY(2 * M); #endif // ZERO FILE *fp = fopen("/proc/meminfo", "r"); diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os/solaris/vm/jvm_solaris.h --- a/hotspot/src/os/solaris/vm/jvm_solaris.h Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os/solaris/vm/jvm_solaris.h Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,9 @@ * JNI conversion, which should be sorted out later. */ +#define __USE_LEGACY_PROTOTYPES__ #include /* For DIR */ +#undef __USE_LEGACY_PROTOTYPES__ #include /* For MAXPATHLEN */ #include /* For socklen_t */ #include /* For F_OK, R_OK, W_OK */ diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp --- a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,6 +28,9 @@ #include "runtime/orderAccess.hpp" +// Compiler version last used for testing: xlc 12 +// Please update this information when this file changes + // Implementation of class OrderAccess. // @@ -61,86 +64,30 @@ #define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); #define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); #define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); -#define inlasm_release() inlasm_lwsync(); -#define inlasm_acquire() inlasm_lwsync(); // Use twi-isync for load_acquire (faster than lwsync). // ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"): // #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); #define inlasm_acquire_reg(X) inlasm_lwsync(); -#define inlasm_fence() inlasm_sync(); -inline void OrderAccess::loadload() { inlasm_lwsync(); } -inline void OrderAccess::storestore() { inlasm_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_lwsync(); } -inline void OrderAccess::storeload() { inlasm_fence(); } - -inline void OrderAccess::acquire() { inlasm_acquire(); } -inline void OrderAccess::release() { inlasm_release(); } -inline void OrderAccess::fence() { inlasm_fence(); } - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_acquire_reg(t); return t; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_acquire_reg(t); return t; } -inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_acquire_reg(t); return t; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_acquire_reg(t); return t; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_acquire_reg(t); return t; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_acquire_reg(t); return t; } -inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_acquire_reg(t); return t; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_acquire(); return t; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_acquire(); return t; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_sync(); } -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; } +inline void OrderAccess::acquire() { inlasm_lwsync(); } +inline void OrderAccess::release() { inlasm_lwsync(); } +inline void OrderAccess::fence() { inlasm_sync(); } -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; inlasm_fence(); } +template<> inline jbyte OrderAccess::specialized_load_acquire (volatile jbyte* p) { register jbyte t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jshort OrderAccess::specialized_load_acquire(volatile jshort* p) { register jshort t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jint OrderAccess::specialized_load_acquire (volatile jint* p) { register jint t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jlong OrderAccess::specialized_load_acquire (volatile jlong* p) { register jlong t = load(p); inlasm_acquire_reg(t); return t; } #undef inlasm_sync #undef inlasm_lwsync #undef inlasm_eieio #undef inlasm_isync -#undef inlasm_release -#undef inlasm_acquire -#undef inlasm_fence + +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp --- a/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,27 +29,27 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: clang 5.1 +// Please update this information when this file changes + +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +static inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); +} + +// x86 is TSO and hence only needs a fence for storeload +// However, a compiler barrier is still needed to prevent reordering +// between volatile and non-volatile memory accesses. + // Implementation of class OrderAccess. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { - volatile intptr_t local_dummy; -#ifdef AMD64 - __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); -#else - __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); -#endif // AMD64 -} - -inline void OrderAccess::release() { - // Avoid hitting the same cache-line from - // different threads. - volatile jint local_dummy = 0; -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { if (os::is_MP()) { @@ -60,156 +60,50 @@ __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); #endif } + compiler_barrier(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jbyte* p, jbyte v) { __asm__ volatile ( "xchgb (%2),%0" : "=q" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jshort* p, jshort v) { __asm__ volatile ( "xchgw (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jint* p, jint v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jint* p, jint v) { __asm__ volatile ( "xchgl (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { #ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - *p = v; fence(); -#endif // AMD64 -} - -// AMD64 copied the bodies for the the signed version. 32bit did this. As long as the -// compiler does the inlining this is simpler. -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } -inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } -inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::store_ptr_fence(void** p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { - __asm__ volatile ( "xchgb (%2),%0" - : "=q" (v) - : "0" (v), "r" (p) - : "memory"); -} -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { - __asm__ volatile ( "xchgw (%2),%0" +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jlong* p, jlong v) { + __asm__ volatile ( "xchgq (%2), %0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { - __asm__ volatile ( "xchgl (%2),%0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -} +#endif // AMD64 -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store(p, v); fence(); -#endif // AMD64 +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jfloat* p, jfloat v) { + release_store_fence((volatile jint*)p, jint_cast(v)); +} +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jdouble* p, jdouble v) { + release_store_fence((volatile jlong*)p, jlong_cast(v)); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } - -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp --- a/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -40,8 +40,7 @@ #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) #define FULL_MEM_BARRIER __kernel_dmb() -#define READ_MEM_BARRIER __kernel_dmb() -#define WRITE_MEM_BARRIER __kernel_dmb() +#define LIGHT_MEM_BARRIER __kernel_dmb() #else // ARM @@ -50,126 +49,31 @@ #ifdef PPC #ifdef __NO_LWSYNC__ -#define READ_MEM_BARRIER __asm __volatile ("sync":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("sync":::"memory") #else -#define READ_MEM_BARRIER __asm __volatile ("lwsync":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("lwsync":::"memory") #endif #else // PPC -#define READ_MEM_BARRIER __asm __volatile ("":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("":::"memory") #endif // PPC #endif // ARM - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -inline void OrderAccess::acquire() { - READ_MEM_BARRIER; -} - -inline void OrderAccess::release() { - WRITE_MEM_BARRIER; -} - -inline void OrderAccess::fence() { - FULL_MEM_BARRIER; -} - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte data = *p; acquire(); return data; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort data = *p; acquire(); return data; } -inline jint OrderAccess::load_acquire(volatile jint* p) { jint data = *p; acquire(); return data; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { - jlong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte data = *p; acquire(); return data; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort data = *p; acquire(); return data; } -inline juint OrderAccess::load_acquire(volatile juint* p) { juint data = *p; acquire(); return data; } -inline julong OrderAccess::load_acquire(volatile julong* p) { - julong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat data = *p; acquire(); return data; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { - jdouble tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} +// Note: What is meant by LIGHT_MEM_BARRIER is a barrier which is sufficient +// to provide TSO semantics, i.e. StoreStore | LoadLoad | LoadStore. -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { - intptr_t data = *p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { - void *data = *(void* volatile *)p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { - void *data = *(void* const volatile *)p; - acquire(); - return data; -} - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) -{ release(); os::atomic_copy64(&v, p); } +inline void OrderAccess::loadload() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storestore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::loadstore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storeload() { FULL_MEM_BARRIER; } -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) -{ release(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); } +inline void OrderAccess::acquire() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::release() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::fence() { FULL_MEM_BARRIER; } -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_ptr(p, v); fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp --- a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,6 +32,9 @@ #error "OrderAccess currently only implemented for PPC64" #endif +// Compiler version last used for testing: gcc 4.1.2 +// Please update this information when this file changes + // Implementation of class OrderAccess. // @@ -65,84 +68,29 @@ #define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); #define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); #define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); -#define inlasm_release() inlasm_lwsync(); -#define inlasm_acquire() inlasm_lwsync(); // Use twi-isync for load_acquire (faster than lwsync). #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); -#define inlasm_fence() inlasm_sync(); -inline void OrderAccess::loadload() { inlasm_lwsync(); } -inline void OrderAccess::storestore() { inlasm_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_lwsync(); } -inline void OrderAccess::storeload() { inlasm_fence(); } - -inline void OrderAccess::acquire() { inlasm_acquire(); } -inline void OrderAccess::release() { inlasm_release(); } -inline void OrderAccess::fence() { inlasm_fence(); } - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_acquire_reg(t); return t; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_acquire_reg(t); return t; } -inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_acquire_reg(t); return t; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_acquire_reg(t); return t; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_acquire_reg(t); return t; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_acquire_reg(t); return t; } -inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_acquire_reg(t); return t; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_acquire(); return t; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_acquire(); return t; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_sync(); } -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; } +inline void OrderAccess::acquire() { inlasm_lwsync(); } +inline void OrderAccess::release() { inlasm_lwsync(); } +inline void OrderAccess::fence() { inlasm_sync(); } -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; inlasm_fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; inlasm_fence(); } +template<> inline jbyte OrderAccess::specialized_load_acquire (volatile jbyte* p) { register jbyte t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jshort OrderAccess::specialized_load_acquire(volatile jshort* p) { register jshort t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jint OrderAccess::specialized_load_acquire (volatile jint* p) { register jint t = load(p); inlasm_acquire_reg(t); return t; } +template<> inline jlong OrderAccess::specialized_load_acquire (volatile jlong* p) { register jlong t = load(p); inlasm_acquire_reg(t); return t; } #undef inlasm_sync #undef inlasm_lwsync #undef inlasm_eieio #undef inlasm_isync -#undef inlasm_release -#undef inlasm_acquire -#undef inlasm_fence +#undef inlasm_acquire_reg + +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_PPC_VM_ORDERACCESS_LINUX_PPC_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp --- a/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,81 +29,25 @@ // Implementation of class OrderAccess. -// Assume TSO. - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -inline void OrderAccess::acquire() { - __asm__ volatile ("nop" : : :); -} - -inline void OrderAccess::release() { - jint* local_dummy = (jint*)&local_dummy; - __asm__ volatile("stw %%g0, [%0]" : : "r" (local_dummy) : "memory"); -} - -inline void OrderAccess::fence() { - __asm__ volatile ("membar #StoreLoad" : : :); +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +static inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } +// Assume TSO. -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } +inline void OrderAccess::fence() { + __asm__ volatile ("membar #StoreLoad" : : : "memory"); +} -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_SPARC_VM_ORDERACCESS_LINUX_SPARC_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp --- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,9 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: gcc 4.8.2 +// Please update this information when this file changes + // Implementation of class OrderAccess. // A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions @@ -36,23 +39,13 @@ __asm__ volatile ("" : : : "memory"); } -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { - volatile intptr_t local_dummy; -#ifdef AMD64 - __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); -#else - __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); -#endif // AMD64 -} - -inline void OrderAccess::release() { - compiler_barrier(); -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { if (os::is_MP()) { @@ -63,156 +56,50 @@ __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); #endif } + compiler_barrier(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte v = *p; compiler_barrier(); return v; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort v = *p; compiler_barrier(); return v; } -inline jint OrderAccess::load_acquire(volatile jint* p) { jint v = *p; compiler_barrier(); return v; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { jlong v = Atomic::load(p); compiler_barrier(); return v; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte v = *p; compiler_barrier(); return v; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort v = *p; compiler_barrier(); return v; } -inline juint OrderAccess::load_acquire(volatile juint* p) { juint v = *p; compiler_barrier(); return v; } -inline julong OrderAccess::load_acquire(volatile julong* p) { julong v = Atomic::load((volatile jlong*)p); compiler_barrier(); return v; } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat v = *p; compiler_barrier(); return v; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { jdouble v = jdouble_cast(Atomic::load((volatile jlong*)p)); compiler_barrier(); return v; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { intptr_t v = *p; compiler_barrier(); return v; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { void* v = *(void* volatile *)p; compiler_barrier(); return v; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { void* v = *(void* const volatile *)p; compiler_barrier(); return v; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { compiler_barrier(); Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { compiler_barrier(); Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong *)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { compiler_barrier(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { compiler_barrier(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jbyte* p, jbyte v) { __asm__ volatile ( "xchgb (%2),%0" : "=q" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jshort* p, jshort v) { __asm__ volatile ( "xchgw (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jint* p, jint v) { +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jint* p, jint v) { __asm__ volatile ( "xchgl (%2),%0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { #ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - *p = v; fence(); -#endif // AMD64 -} - -// AMD64 copied the bodies for the the signed version. 32bit did this. As long as the -// compiler does the inlining this is simpler. -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } -inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } -inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { store_fence((jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::store_ptr_fence(void** p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ("xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} - -// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { - __asm__ volatile ( "xchgb (%2),%0" - : "=q" (v) - : "0" (v), "r" (p) - : "memory"); -} -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { - __asm__ volatile ( "xchgw (%2),%0" +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jlong* p, jlong v) { + __asm__ volatile ( "xchgq (%2), %0" : "=r" (v) : "0" (v), "r" (p) : "memory"); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { - __asm__ volatile ( "xchgl (%2),%0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -} +#endif // AMD64 -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store(p, v); fence(); -#endif // AMD64 +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jfloat* p, jfloat v) { + release_store_fence((volatile jint*)p, jint_cast(v)); +} +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jdouble* p, jdouble v) { + release_store_fence((volatile jlong*)p, jlong_cast(v)); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } - -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { -#ifdef AMD64 - __asm__ __volatile__ ( "xchgq (%2), %0" - : "=r" (v) - : "0" (v), "r" (p) - : "memory"); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp --- a/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -40,8 +40,7 @@ #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) #define FULL_MEM_BARRIER __kernel_dmb() -#define READ_MEM_BARRIER __kernel_dmb() -#define WRITE_MEM_BARRIER __kernel_dmb() +#define LIGHT_MEM_BARRIER __kernel_dmb() #else // ARM @@ -49,126 +48,33 @@ #ifdef PPC -#define READ_MEM_BARRIER __asm __volatile ("isync":::"memory") #ifdef __NO_LWSYNC__ -#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("sync":::"memory") #else -#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("lwsync":::"memory") #endif #else // PPC -#define READ_MEM_BARRIER __asm __volatile ("":::"memory") -#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory") +#define LIGHT_MEM_BARRIER __asm __volatile ("":::"memory") #endif // PPC #endif // ARM - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -inline void OrderAccess::acquire() { - READ_MEM_BARRIER; -} - -inline void OrderAccess::release() { - WRITE_MEM_BARRIER; -} - -inline void OrderAccess::fence() { - FULL_MEM_BARRIER; -} - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte data = *p; acquire(); return data; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort data = *p; acquire(); return data; } -inline jint OrderAccess::load_acquire(volatile jint* p) { jint data = *p; acquire(); return data; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { - jlong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte data = *p; acquire(); return data; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort data = *p; acquire(); return data; } -inline juint OrderAccess::load_acquire(volatile juint* p) { juint data = *p; acquire(); return data; } -inline julong OrderAccess::load_acquire(volatile julong* p) { - julong tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat data = *p; acquire(); return data; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { - jdouble tmp; - os::atomic_copy64(p, &tmp); - acquire(); - return tmp; -} +// Note: What is meant by LIGHT_MEM_BARRIER is a barrier which is sufficient +// to provide TSO semantics, i.e. StoreStore | LoadLoad | LoadStore. -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { - intptr_t data = *p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { - void *data = *(void* volatile *)p; - acquire(); - return data; -} -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { - void *data = *(void* const volatile *)p; - acquire(); - return data; -} - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) -{ release(); os::atomic_copy64(&v, p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) -{ release(); os::atomic_copy64(&v, p); } +inline void OrderAccess::loadload() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storestore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::loadstore() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::storeload() { FULL_MEM_BARRIER; } -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) -{ release(); *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { os::atomic_copy64(&v, p); fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); } +inline void OrderAccess::acquire() { LIGHT_MEM_BARRIER; } +inline void OrderAccess::release() { LIGHT_MEM_BARRIER; } -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } +inline void OrderAccess::fence() { FULL_MEM_BARRIER; } -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_ptr(p, v); fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_LINUX_ZERO_VM_ORDERACCESS_LINUX_ZERO_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,107 +28,30 @@ #include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" +// Compiler version last used for testing: solaris studio 12u3 +// Please update this information when this file changes + // Implementation of class OrderAccess. // Assume TSO. -// In solaris_sparc.il -extern "C" void _OrderAccess_acquire(); -extern "C" void _OrderAccess_fence(); - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -#ifdef _GNU_SOURCE - -inline void OrderAccess::acquire() { - __asm__ volatile ("nop" : : :); -} - -inline void OrderAccess::release() { - jint* local_dummy = (jint*)&local_dummy; - __asm__ volatile("stw %%g0, [%0]" : : "r" (local_dummy) : "memory"); -} - -inline void OrderAccess::fence() { - __asm__ volatile ("membar #StoreLoad" : : :); -} - -#else // _GNU_SOURCE - -inline void OrderAccess::acquire() { - _OrderAccess_acquire(); -} - -inline void OrderAccess::release() { - // Avoid hitting the same cache-line from - // different threads. - volatile jint local_dummy = 0; -} - -inline void OrderAccess::fence() { - _OrderAccess_fence(); +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); } -#endif // _GNU_SOURCE - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } +inline void OrderAccess::fence() { + __asm__ volatile ("membar #StoreLoad" : : : "memory"); +} -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_SOLARIS_SPARC_VM_ORDERACCESS_SOLARIS_SPARC_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il --- a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ // -// Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2002, 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 @@ -19,7 +19,7 @@ // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA // or visit www.oracle.com if you need additional information or have any // questions. -// +// // // Get the raw thread ID from %g7 @@ -35,11 +35,11 @@ // Clear SPARC fprs.FEF DU and DL bits -- // allows the kernel to avoid saving FPU state at context-switch time. // Use for state-transition points (into _thread_blocked) or when - // parking. - + // parking. + .inline _mark_fpu_nosave, 0 .volatile - wr %g0, 0, %fprs + wr %g0, 0, %fprs .nonvolatile .end @@ -85,7 +85,7 @@ // Support for jint Atomic::cmpxchg(jint exchange_value, - // volatile jint* dest, + // volatile jint* dest, // jint compare_value) // // Arguments: @@ -103,8 +103,8 @@ .end - // Support for intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, - // volatile intptr_t* dest, + // Support for intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, + // volatile intptr_t* dest, // intptr_t compare_value) // // 64-bit @@ -124,8 +124,8 @@ .end - // Support for jlong Atomic::cmpxchg(jlong exchange_value, - // volatile jlong* dest, + // Support for jlong Atomic::cmpxchg(jlong exchange_value, + // volatile jlong* dest, // jlong compare_value) // // 32-bit calling conventions @@ -221,27 +221,6 @@ .end - // Support for void OrderAccess::acquire() - // The method is intentionally empty. - // It exists for the sole purpose of generating - // a C/C++ sequence point over which the compiler won't - // reorder code. - - .inline _OrderAccess_acquire,0 - .volatile - .nonvolatile - .end - - - // Support for void OrderAccess::fence() - - .inline _OrderAccess_fence,0 - .volatile - membar #StoreLoad - .nonvolatile - .end - - // Support for void Prefetch::read(void *loc, intx interval) // // Prefetch for several reads. diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp --- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,110 +29,35 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: solaris studio 12u3 +// Please update this information when this file changes + // Implementation of class OrderAccess. -// For Sun Studio - implementation is in solaris_i486.il. -// For gcc - implementation is just below. -extern "C" void _OrderAccess_acquire(); -extern "C" void _OrderAccess_fence(); - -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } -inline void OrderAccess::storeload() { fence(); } - -inline void OrderAccess::acquire() { - _OrderAccess_acquire(); - +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +inline void compiler_barrier() { + __asm__ volatile ("" : : : "memory"); } -inline void OrderAccess::release() { - // Avoid hitting the same cache-line from - // different threads. - volatile jint local_dummy = 0; -} +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { if (os::is_MP()) { - _OrderAccess_fence(); +#ifdef AMD64 + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); +#else + __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); +#endif } -} - -#ifdef _GNU_SOURCE - -extern "C" { - inline void _OrderAccess_acquire() { - volatile intptr_t local_dummy; -#ifdef AMD64 - __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); -#else - __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); -#endif // AMD64 - } - inline void _OrderAccess_fence() { - // Always use locked addl since mfence is sometimes expensive - __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); - } - + compiler_barrier(); } -#endif // GNU_SOURCE - -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } - -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store((jlong *)p, (jlong)v); fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -19,7 +19,7 @@ // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA // or visit www.oracle.com if you need additional information or have any // questions. -// +// // @@ -34,19 +34,19 @@ // Get the raw thread ID from %gs:0 .inline _raw_thread_id,0 - movl %gs:0, %eax + movl %gs:0, %eax .end // Get current sp .inline _get_current_sp,0 .volatile - movl %esp, %eax + movl %esp, %eax .end // Get current fp .inline _get_current_fp,0 .volatile - movl %ebp, %eax + movl %ebp, %eax .end // Support for os::rdtsc() @@ -76,8 +76,8 @@ xchgl (%ecx), %eax .end - // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, - // volatile jbyte *dest, + // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, + // volatile jbyte *dest, // jbyte compare_value) // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg_byte,4 @@ -93,8 +93,8 @@ 2: .end - // Support for jint Atomic::cmpxchg(jint exchange_value, - // volatile jint *dest, + // Support for jint Atomic::cmpxchg(jint exchange_value, + // volatile jint *dest, // jint compare_value) // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg,4 @@ -141,17 +141,6 @@ fistpll (%eax) .end - // Support for OrderAccess::acquire() - .inline _OrderAccess_acquire,0 - movl 0(%esp), %eax - .end - - // Support for OrderAccess::fence() - .inline _OrderAccess_fence,0 - lock - addl $0, (%esp) - .end - // Support for u2 Bytes::swap_u2(u2 x) .inline _raw_swap_u2,1 movl 0(%esp), %eax diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ // -// Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2004, 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 @@ -19,7 +19,7 @@ // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA // or visit www.oracle.com if you need additional information or have any // questions. -// +// // // The argument size of each inline directive is ignored by the compiler @@ -27,19 +27,19 @@ // Get the raw thread ID from %gs:0 .inline _raw_thread_id,0 - movq %fs:0, %rax + movq %fs:0, %rax .end // Get current sp .inline _get_current_sp,0 .volatile - movq %rsp, %rax + movq %rsp, %rax .end // Get current fp .inline _get_current_fp,0 .volatile - movq %rbp, %rax + movq %rbp, %rax .end // Support for os::rdtsc() @@ -77,8 +77,8 @@ movq %rdi, %rax .end - // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, - // volatile jbyte *dest, + // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, + // volatile jbyte *dest, // jbyte compare_value) .inline _Atomic_cmpxchg_byte,3 movb %dl, %al // compare_value @@ -86,8 +86,8 @@ cmpxchgb %dil, (%rsi) .end - // Support for jint Atomic::cmpxchg(jint exchange_value, - // volatile jint *dest, + // Support for jint Atomic::cmpxchg(jint exchange_value, + // volatile jint *dest, // jint compare_value) .inline _Atomic_cmpxchg,3 movl %edx, %eax // compare_value @@ -104,17 +104,6 @@ cmpxchgq %rdi, (%rsi) .end - // Support for OrderAccess::acquire() - .inline _OrderAccess_acquire,0 - movl 0(%rsp), %eax - .end - - // Support for OrderAccess::fence() - .inline _OrderAccess_fence,0 - lock - addl $0, (%rsp) - .end - // Support for u2 Bytes::swap_u2(u2 x) .inline _raw_swap_u2,1 movw %di, %ax diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp --- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,29 +25,39 @@ #ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP #define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP +#include #include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" +// Compiler version last used for testing: Microsoft Visual Studio 2010 +// Please update this information when this file changes + // Implementation of class OrderAccess. -inline void OrderAccess::loadload() { acquire(); } -inline void OrderAccess::storestore() { release(); } -inline void OrderAccess::loadstore() { acquire(); } +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions +inline void compiler_barrier() { + _ReadWriteBarrier(); +} + +// Note that in MSVC, volatile memory accesses are explicitly +// guaranteed to have acquire release semantics (w.r.t. compiler +// reordering) and therefore does not even need a compiler barrier +// for normal acquire release accesses. And all generalized +// bound calls like release_store go through OrderAccess::load +// and OrderAccess::store which do volatile memory accesses. +template<> inline void ScopedFence::postfix() { } +template<> inline void ScopedFence::prefix() { } +template<> inline void ScopedFence::prefix() { } +template<> inline void ScopedFence::postfix() { OrderAccess::fence(); } + +inline void OrderAccess::loadload() { compiler_barrier(); } +inline void OrderAccess::storestore() { compiler_barrier(); } +inline void OrderAccess::loadstore() { compiler_barrier(); } inline void OrderAccess::storeload() { fence(); } -inline void OrderAccess::acquire() { -#ifndef AMD64 - __asm { - mov eax, dword ptr [esp]; - } -#endif // !AMD64 -} - -inline void OrderAccess::release() { - // A volatile store has release semantics. - volatile jint local_dummy = 0; -} +inline void OrderAccess::acquire() { compiler_barrier(); } +inline void OrderAccess::release() { compiler_barrier(); } inline void OrderAccess::fence() { #ifdef AMD64 @@ -59,157 +69,47 @@ } } #endif // AMD64 + compiler_barrier(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } -inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } -inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } - -inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } -inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } -inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } - -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } - -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { -#ifdef AMD64 - *p = v; fence(); -#else +#ifndef AMD64 +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jbyte* p, jbyte v) { __asm { mov edx, p; mov al, v; xchg al, byte ptr [edx]; } -#endif // AMD64 } -inline void OrderAccess::store_fence(jshort* p, jshort v) { -#ifdef AMD64 - *p = v; fence(); -#else +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jshort* p, jshort v) { __asm { mov edx, p; mov ax, v; xchg ax, word ptr [edx]; } -#endif // AMD64 } -inline void OrderAccess::store_fence(jint* p, jint v) { -#ifdef AMD64 - *p = v; fence(); -#else +template<> +inline void OrderAccess::specialized_release_store_fence (volatile jint* p, jint v) { __asm { mov edx, p; mov eax, v; xchg eax, dword ptr [edx]; } +} #endif // AMD64 -} - -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } -inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } -inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } - -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { -#ifdef AMD64 - *p = v; fence(); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 -} -inline void OrderAccess::store_ptr_fence(void** p, void* v) { -#ifdef AMD64 - *p = v; fence(); -#else - store_fence((jint*)p, (jint)v); -#endif // AMD64 +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jfloat* p, jfloat v) { + release_store_fence((volatile jint*)p, jint_cast(v)); } - -// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { -#ifdef AMD64 - *p = v; fence(); -#else - __asm { - mov edx, p; - mov al, v; - xchg al, byte ptr [edx]; - } -#endif // AMD64 +template<> +inline void OrderAccess::specialized_release_store_fence(volatile jdouble* p, jdouble v) { + release_store_fence((volatile jlong*)p, jlong_cast(v)); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { -#ifdef AMD64 - *p = v; fence(); -#else - __asm { - mov edx, p; - mov ax, v; - xchg ax, word ptr [edx]; - } -#endif // AMD64 -} - -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { -#ifdef AMD64 - *p = v; fence(); -#else - __asm { - mov edx, p; - mov eax, v; - xchg eax, dword ptr [edx]; - } -#endif // AMD64 -} - -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } - -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); } - -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { -#ifdef AMD64 - *p = v; fence(); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} - -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { -#ifdef AMD64 - *(void* volatile *)p = v; fence(); -#else - release_store_fence((volatile jint*)p, (jint)v); -#endif // AMD64 -} +#define VM_HAS_GENERALIZED_ORDER_ACCESS 1 #endif // OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/c1/c1_LIR.cpp --- a/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -142,16 +142,11 @@ #ifndef PRODUCT -void LIR_Address::verify() const { +void LIR_Address::verify0() const { #if defined(SPARC) || defined(PPC) assert(scale() == times_1, "Scaled addressing mode not available on SPARC/PPC and should not be used"); assert(disp() == 0 || index()->is_illegal(), "can't have both"); #endif -#ifdef ARM - assert(disp() == 0 || index()->is_illegal(), "can't have both"); - // Note: offsets higher than 4096 must not be rejected here. They can - // be handled by the back-end or will be rejected if not. -#endif #ifdef _LP64 assert(base()->is_cpu_register(), "wrong base operand"); #ifndef AARCH64 diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/c1/c1_LIR.hpp --- a/hotspot/src/share/vm/c1/c1_LIR.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_C1_C1_LIR_HPP #define SHARE_VM_C1_C1_LIR_HPP +#include "c1/c1_Defs.hpp" #include "c1/c1_ValueType.hpp" #include "oops/method.hpp" @@ -561,7 +562,13 @@ virtual BasicType type() const { return _type; } virtual void print_value_on(outputStream* out) const PRODUCT_RETURN; - void verify() const PRODUCT_RETURN; + void verify0() const PRODUCT_RETURN; +#if defined(LIR_ADDRESS_PD_VERIFY) && !defined(PRODUCT) + void pd_verify() const; + void verify() const { pd_verify(); } +#else + void verify() const { verify0(); } +#endif static Scale scale(BasicType type); }; @@ -610,7 +617,7 @@ LIR_OprDesc::float_type | LIR_OprDesc::fpu_register | LIR_OprDesc::single_size); } -#if defined(ARM) +#if defined(ARM32) static LIR_Opr double_fpu(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::fpu_register | LIR_OprDesc::double_size); } static LIR_Opr single_softfp(int reg) { return (LIR_Opr)((reg << LIR_OprDesc::reg1_shift) | LIR_OprDesc::float_type | LIR_OprDesc::cpu_register | LIR_OprDesc::single_size); } static LIR_Opr double_softfp(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::cpu_register | LIR_OprDesc::double_size); } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "c1/c1_Defs.hpp" #include "c1/c1_Compilation.hpp" #include "c1/c1_FrameMap.hpp" #include "c1/c1_Instruction.hpp" @@ -49,10 +50,7 @@ #define __ gen()->lir()-> #endif -// TODO: ARM - Use some recognizable constant which still fits architectural constraints -#ifdef ARM -#define PATCHED_ADDR (204) -#else +#ifndef PATCHED_ADDR #define PATCHED_ADDR (max_jint) #endif @@ -1600,24 +1598,9 @@ } assert(addr->is_register(), "must be a register at this point"); -#ifdef ARM - // TODO: ARM - move to platform-dependent code - LIR_Opr tmp = FrameMap::R14_opr; - if (VM_Version::supports_movw()) { - __ move((LIR_Opr)card_table_base, tmp); - } else { - __ move(new LIR_Address(FrameMap::Rthread_opr, in_bytes(JavaThread::card_table_base_offset()), T_ADDRESS), tmp); - } - - LIR_Address *card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTableModRefBS::card_shift, 0, T_BYTE); - if(((int)ct->byte_map_base & 0xff) == 0) { - __ move(tmp, card_addr); - } else { - LIR_Opr tmp_zero = new_register(T_INT); - __ move(LIR_OprFact::intConst(0), tmp_zero); - __ move(tmp_zero, card_addr); - } -#else // ARM +#ifdef CARDTABLEMODREF_POST_BARRIER_HELPER + CardTableModRef_post_barrier_helper(addr, card_table_base); +#else LIR_Opr tmp = new_pointer_register(); if (TwoOperandLIRForm) { __ move(addr, tmp); @@ -1633,7 +1616,7 @@ new LIR_Address(tmp, load_constant(card_table_base), T_BYTE)); } -#endif // ARM +#endif } @@ -2123,7 +2106,7 @@ } else { #ifdef X86 addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type); -#elif defined(ARM) +#elif defined(GENERATE_ADDRESS_IS_PREFERRED) addr = generate_address(base_op, index_op, log2_scale, 0, dst_type); #else if (index_op->is_illegal() || log2_scale == 0) { @@ -2177,6 +2160,9 @@ LIR_Opr base_op = base.result(); LIR_Opr index_op = idx.result(); +#ifdef GENERATE_ADDRESS_IS_PREFERRED + LIR_Address* addr = generate_address(base_op, index_op, log2_scale, 0, x->basic_type()); +#else #ifndef _LP64 if (base_op->type() == T_LONG) { base_op = new_register(T_INT); @@ -2210,6 +2196,7 @@ } LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type()); +#endif // !GENERATE_ADDRESS_IS_PREFERRED __ move(value.result(), addr); } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/c1/c1_LIRGenerator.hpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -275,6 +275,9 @@ void G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val); void CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val); +#ifdef CARDTABLEMODREF_POST_BARRIER_HELPER + void CardTableModRef_post_barrier_helper(LIR_OprDesc* addr, LIR_Const* card_table_base); +#endif static LIR_Opr result_register_for(ValueType* type, bool callee = false); @@ -546,6 +549,10 @@ #ifdef ASSERT virtual void do_Assert (Assert* x); #endif + +#ifdef C1_LIRGENERATOR_MD_HPP +#include C1_LIRGENERATOR_MD_HPP +#endif }; diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -2123,7 +2123,7 @@ assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register"); assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even"); LIR_Opr result = LIR_OprFact::double_fpu(interval->assigned_regHi() - pd_first_fpu_reg, assigned_reg - pd_first_fpu_reg); -#elif defined(ARM) +#elif defined(ARM32) assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register"); assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register"); assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even"); @@ -2712,7 +2712,7 @@ #ifdef SPARC assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)"); #endif -#ifdef ARM +#ifdef ARM32 assert(opr->fpu_regnrHi() == opr->fpu_regnrLo() + 1, "assumed in calculation (only fpu_regnrLo is used)"); #endif #ifdef PPC diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/c1/c1_Runtime1.cpp --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1120,7 +1120,7 @@ #ifdef ARM if((load_klass_or_mirror_patch_id || stub_id == Runtime1::load_appendix_patching_id) && - !VM_Version::supports_movw()) { + nativeMovConstReg_at(copy_buff)->is_pc_relative()) { nmethod* nm = CodeCache::find_nmethod(instr_pc); address addr = NULL; assert(nm != NULL, "invalid nmethod_pc"); diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -902,7 +902,7 @@ } Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() { - Klass* head = (Klass*)_next_klass; + Klass* head = _next_klass; while (head != NULL) { Klass* next = next_klass_in_cldg(head); diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -315,7 +315,7 @@ // An iterator that distributes Klasses to parallel worker threads. class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj { - volatile Klass* _next_klass; + Klass* volatile _next_klass; public: ClassLoaderDataGraphKlassIteratorAtomic(); Klass* next_klass(); diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -549,7 +549,7 @@ FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4); } if (ConcGCThreads > 1) { - _conc_workers = new YieldingFlexibleWorkGang("Parallel CMS Threads", + _conc_workers = new YieldingFlexibleWorkGang("CMS Thread", ConcGCThreads, true); if (_conc_workers == NULL) { warning("GC/CMS: _conc_workers allocation failure: " diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -65,7 +65,7 @@ assert(_collector == NULL, "Collector already set"); _collector = collector; - set_name("Concurrent Mark-Sweep GC Thread"); + set_name("CMS Main Thread"); if (os::create_thread(this, os::cgc_thread)) { // An old comment here said: "Priority should be just less diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -61,7 +61,7 @@ create_and_start(); // set name - set_name("G1 Concurrent Refinement Thread#%d", worker_id); + set_name("G1 Refine#%d", worker_id); } void ConcurrentG1RefineThread::initialize() { diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -687,7 +687,7 @@ gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor()); #endif - _parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads", + _parallel_workers = new FlexibleWorkGang("G1 Marker", _max_parallel_marking_threads, false, true); if (_parallel_workers == NULL) { vm_exit_during_initialization("Failed necessary allocation."); @@ -3561,6 +3561,15 @@ _termination_start_time_ms = 0.0; #if _MARKING_STATS_ + _aborted = 0; + _aborted_overflow = 0; + _aborted_cm_aborted = 0; + _aborted_yield = 0; + _aborted_timed_out = 0; + _aborted_satb = 0; + _aborted_termination = 0; + _steal_attempts = 0; + _steals = 0; _local_pushes = 0; _local_pops = 0; _local_max_size = 0; @@ -3573,15 +3582,6 @@ _regions_claimed = 0; _objs_found_on_bitmap = 0; _satb_buffers_processed = 0; - _steal_attempts = 0; - _steals = 0; - _aborted = 0; - _aborted_overflow = 0; - _aborted_cm_aborted = 0; - _aborted_yield = 0; - _aborted_timed_out = 0; - _aborted_satb = 0; - _aborted_termination = 0; #endif // _MARKING_STATS_ } @@ -3742,7 +3742,7 @@ gclog_or_tty->print_cr("[%u] pushed %d entries to the global stack", _worker_id, n); } - statsOnly( int tmp_size = _cm->mark_stack_size(); + statsOnly( size_t tmp_size = _cm->mark_stack_size(); if (tmp_size > _global_max_size) { _global_max_size = tmp_size; } @@ -3777,7 +3777,7 @@ assert(success, "invariant"); } - statsOnly( int tmp_size = _task_queue->size(); + statsOnly( size_t tmp_size = (size_t)_task_queue->size(); if (tmp_size > _local_max_size) { _local_max_size = tmp_size; } @@ -3934,24 +3934,24 @@ gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms", _all_clock_intervals_ms.maximum(), _all_clock_intervals_ms.sum()); - gclog_or_tty->print_cr(" Clock Causes (cum): scanning = %d, marking = %d", + gclog_or_tty->print_cr(" Clock Causes (cum): scanning = " SIZE_FORMAT ", marking = " SIZE_FORMAT, _clock_due_to_scanning, _clock_due_to_marking); - gclog_or_tty->print_cr(" Objects: scanned = %d, found on the bitmap = %d", + gclog_or_tty->print_cr(" Objects: scanned = " SIZE_FORMAT ", found on the bitmap = " SIZE_FORMAT, _objs_scanned, _objs_found_on_bitmap); - gclog_or_tty->print_cr(" Local Queue: pushes = %d, pops = %d, max size = %d", + gclog_or_tty->print_cr(" Local Queue: pushes = " SIZE_FORMAT ", pops = " SIZE_FORMAT ", max size = " SIZE_FORMAT, _local_pushes, _local_pops, _local_max_size); - gclog_or_tty->print_cr(" Global Stack: pushes = %d, pops = %d, max size = %d", + gclog_or_tty->print_cr(" Global Stack: pushes = " SIZE_FORMAT ", pops = " SIZE_FORMAT ", max size = " SIZE_FORMAT, _global_pushes, _global_pops, _global_max_size); - gclog_or_tty->print_cr(" transfers to = %d, transfers from = %d", + gclog_or_tty->print_cr(" transfers to = " SIZE_FORMAT ", transfers from = " SIZE_FORMAT, _global_transfers_to,_global_transfers_from); - gclog_or_tty->print_cr(" Regions: claimed = %d", _regions_claimed); - gclog_or_tty->print_cr(" SATB buffers: processed = %d", _satb_buffers_processed); - gclog_or_tty->print_cr(" Steals: attempts = %d, successes = %d", + gclog_or_tty->print_cr(" Regions: claimed = " SIZE_FORMAT, _regions_claimed); + gclog_or_tty->print_cr(" SATB buffers: processed = " SIZE_FORMAT, _satb_buffers_processed); + gclog_or_tty->print_cr(" Steals: attempts = " SIZE_FORMAT ", successes = " SIZE_FORMAT, _steal_attempts, _steals); - gclog_or_tty->print_cr(" Aborted: %d, due to", _aborted); - gclog_or_tty->print_cr(" overflow: %d, global abort: %d, yield: %d", + gclog_or_tty->print_cr(" Aborted: " SIZE_FORMAT ", due to", _aborted); + gclog_or_tty->print_cr(" overflow: " SIZE_FORMAT ", global abort: " SIZE_FORMAT ", yield: " SIZE_FORMAT, _aborted_overflow, _aborted_cm_aborted, _aborted_yield); - gclog_or_tty->print_cr(" time out: %d, SATB: %d, termination: %d", + gclog_or_tty->print_cr(" time out: " SIZE_FORMAT ", SATB: " SIZE_FORMAT ", termination: " SIZE_FORMAT, _aborted_timed_out, _aborted_satb, _aborted_termination); #endif // _MARKING_STATS_ } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1039,36 +1039,36 @@ NumberSeq _all_clock_intervals_ms; double _interval_start_time_ms; - int _aborted; - int _aborted_overflow; - int _aborted_cm_aborted; - int _aborted_yield; - int _aborted_timed_out; - int _aborted_satb; - int _aborted_termination; + size_t _aborted; + size_t _aborted_overflow; + size_t _aborted_cm_aborted; + size_t _aborted_yield; + size_t _aborted_timed_out; + size_t _aborted_satb; + size_t _aborted_termination; - int _steal_attempts; - int _steals; + size_t _steal_attempts; + size_t _steals; - int _clock_due_to_marking; - int _clock_due_to_scanning; + size_t _clock_due_to_marking; + size_t _clock_due_to_scanning; - int _local_pushes; - int _local_pops; - int _local_max_size; - int _objs_scanned; + size_t _local_pushes; + size_t _local_pops; + size_t _local_max_size; + size_t _objs_scanned; - int _global_pushes; - int _global_pops; - int _global_max_size; + size_t _global_pushes; + size_t _global_pops; + size_t _global_max_size; - int _global_transfers_to; - int _global_transfers_from; + size_t _global_transfers_to; + size_t _global_transfers_from; - int _regions_claimed; - int _objs_found_on_bitmap; + size_t _regions_claimed; + size_t _objs_found_on_bitmap; - int _satb_buffers_processed; + size_t _satb_buffers_processed; #endif // _MARKING_STATS_ // it updates the local fields after this task has claimed diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,7 +252,7 @@ assert(success, "invariant"); } - statsOnly( int tmp_size = _task_queue->size(); + statsOnly( size_t tmp_size = (size_t)_task_queue->size(); if (tmp_size > _local_max_size) { _local_max_size = tmp_size; } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ _vtime_accum(0.0), _vtime_mark_accum(0.0) { - set_name("G1 Main Concurrent Mark GC Thread"); + set_name("G1 Main Marker"); create_and_start(); } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -3538,7 +3538,7 @@ r->rem_set()->clear_locked(); } assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty."); - g1h->register_humongous_region_with_in_cset_fast_test(region_idx); + g1h->register_humongous_region_with_cset(region_idx); _candidate_humongous++; } _total_humongous++; @@ -3552,7 +3552,7 @@ void flush_rem_set_entries() { _dcq.flush(); } }; -void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { +void G1CollectedHeap::register_humongous_regions_with_cset() { if (!G1EagerReclaimHumongousObjects) { g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0); return; @@ -3859,7 +3859,7 @@ g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info); - register_humongous_regions_with_in_cset_fast_test(); + register_humongous_regions_with_cset(); assert(check_cset_fast_test(), "Inconsistency in the InCSetState table."); @@ -6077,7 +6077,7 @@ HeapRegion* next = cur->next_in_collection_set(); assert(cur->in_collection_set(), "bad CS"); cur->set_next_in_collection_set(NULL); - cur->set_in_collection_set(false); + clear_in_cset(cur); if (cur->is_young()) { int index = cur->young_index_in_cset(); @@ -6303,7 +6303,7 @@ HeapRegion* next = cur->next_in_collection_set(); assert(cur->in_collection_set(), "bad CS"); cur->set_next_in_collection_set(NULL); - cur->set_in_collection_set(false); + clear_in_cset(cur); cur->set_young_index_in_cset(-1); cur = next; } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -110,6 +110,7 @@ void empty_list(); bool is_empty() { return _length == 0; } uint length() { return _length; } + uint eden_length() { return length() - survivor_length(); } uint survivor_length() { return _survivor_length; } // Currently we do not keep track of the used byte sum for the @@ -119,7 +120,7 @@ // we'll report the more accurate information then. size_t eden_used_bytes() { assert(length() >= survivor_length(), "invariant"); - return (size_t) (length() - survivor_length()) * HeapRegion::GrainBytes; + return (size_t) eden_length() * HeapRegion::GrainBytes; } size_t survivor_used_bytes() { return (size_t) survivor_length() * HeapRegion::GrainBytes; @@ -644,23 +645,21 @@ // is considered a candidate for eager reclamation. bool humongous_region_is_candidate(uint index); // Register the given region to be part of the collection set. - inline void register_humongous_region_with_in_cset_fast_test(uint index); + inline void register_humongous_region_with_cset(uint index); // Register regions with humongous objects (actually on the start region) in // the in_cset_fast_test table. - void register_humongous_regions_with_in_cset_fast_test(); + void register_humongous_regions_with_cset(); // We register a region with the fast "in collection set" test. We // simply set to true the array slot corresponding to this region. - void register_young_region_with_in_cset_fast_test(HeapRegion* r) { + void register_young_region_with_cset(HeapRegion* r) { _in_cset_fast_test.set_in_young(r->hrm_index()); } - void register_old_region_with_in_cset_fast_test(HeapRegion* r) { + void register_old_region_with_cset(HeapRegion* r) { _in_cset_fast_test.set_in_old(r->hrm_index()); } - - // This is a fast test on whether a reference points into the - // collection set or not. Assume that the reference - // points into the heap. - inline bool in_cset_fast_test(oop obj); + void clear_in_cset(const HeapRegion* hr) { + _in_cset_fast_test.clear(hr); + } void clear_cset_fast_test() { _in_cset_fast_test.clear(); @@ -1245,6 +1244,7 @@ // set. Slow implementation. inline bool obj_in_cs(oop obj); + inline bool is_in_cset(const HeapRegion *hr); inline bool is_in_cset(oop obj); inline bool is_in_cset_or_humongous(const oop obj); diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -234,6 +234,10 @@ return ret; } +bool G1CollectedHeap::is_in_cset(const HeapRegion* hr) { + return _in_cset_fast_test.is_in_cset(hr); +} + bool G1CollectedHeap::is_in_cset_or_humongous(const oop obj) { return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj); } @@ -242,7 +246,7 @@ return _in_cset_fast_test.at((HeapWord*)obj); } -void G1CollectedHeap::register_humongous_region_with_in_cset_fast_test(uint index) { +void G1CollectedHeap::register_humongous_region_with_cset(uint index) { _in_cset_fast_test.set_humongous(index); } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -537,15 +537,12 @@ // This is how many young regions we already have (currently: the survivors). uint base_min_length = recorded_survivor_regions(); - // This is the absolute minimum young length, which ensures that we - // can allocate one eden region in the worst-case. - uint absolute_min_length = base_min_length + 1; - uint desired_min_length = - calculate_young_list_desired_min_length(base_min_length); - if (desired_min_length < absolute_min_length) { - desired_min_length = absolute_min_length; - } - + uint desired_min_length = calculate_young_list_desired_min_length(base_min_length); + // This is the absolute minimum young length. Ensure that we + // will at least have one eden region available for allocation. + uint absolute_min_length = base_min_length + MAX2(_g1->young_list()->eden_length(), (uint)1); + // If we shrank the young list target it should not shrink below the current size. + desired_min_length = MAX2(desired_min_length, absolute_min_length); // Calculate the absolute and desired max bounds. // We will try our best not to "eat" into the reserve. @@ -1610,11 +1607,10 @@ assert(hr->is_old(), "the region should be old"); assert(!hr->in_collection_set(), "should not already be in the CSet"); - hr->set_in_collection_set(true); + _g1->register_old_region_with_cset(hr); hr->set_next_in_collection_set(_collection_set); _collection_set = hr; _collection_set_bytes_used_before += hr->used(); - _g1->register_old_region_with_in_cset_fast_test(hr); size_t rs_length = hr->rem_set()->occupied(); _recorded_rs_lengths += rs_length; _old_cset_region_length += 1; @@ -1744,10 +1740,8 @@ _inc_cset_max_finger = MAX2(_inc_cset_max_finger, hr_end); assert(!hr->in_collection_set(), "invariant"); - hr->set_in_collection_set(true); - assert( hr->next_in_collection_set() == NULL, "invariant"); - - _g1->register_young_region_with_in_cset_fast_test(hr); + _g1->register_young_region_with_cset(hr); + assert(hr->next_in_collection_set() == NULL, "invariant"); } // Add the region at the RHS of the incremental cset @@ -1925,7 +1919,7 @@ // [Newly Young Regions ++ Survivors from last pause]. uint survivor_region_length = young_list->survivor_length(); - uint eden_region_length = young_list->length() - survivor_region_length; + uint eden_region_length = young_list->eden_length(); init_cset_region_lengths(eden_region_length, survivor_region_length); HeapRegion* hr = young_list->first_survivor_region(); diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP +#include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/g1BiasedArray.hpp" #include "memory/allocation.hpp" @@ -125,8 +126,10 @@ bool is_in_cset_or_humongous(HeapWord* addr) const { return at(addr).is_in_cset_or_humongous(); } bool is_in_cset(HeapWord* addr) const { return at(addr).is_in_cset(); } + bool is_in_cset(const HeapRegion* hr) const { return get_by_index(hr->hrm_index()).is_in_cset(); } InCSetState at(HeapWord* addr) const { return get_by_address(addr); } void clear() { G1BiasedMappedArray::clear(); } + void clear(const HeapRegion* hr) { return set_by_index(hr->hrm_index(), InCSetState::NotInCSet); } }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -34,7 +34,7 @@ G1StringDedupThread::G1StringDedupThread() : ConcurrentGCThread() { - set_name("String Deduplication Thread"); + set_name("G1 StrDedup"); create_and_start(); } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -162,7 +162,7 @@ "we should have already filtered out humongous regions"); assert(_end == orig_end(), "we should have already filtered out humongous regions"); - assert(!_in_collection_set, + assert(!in_collection_set(), err_msg("Should not clear heap region %u in the collection set", hrm_index())); set_allocation_context(AllocationContext::system()); @@ -262,7 +262,6 @@ _hrm_index(hrm_index), _allocation_context(AllocationContext::system()), _humongous_start_region(NULL), - _in_collection_set(false), _next_in_special_set(NULL), _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -236,8 +236,6 @@ // For a humongous region, region in which it starts. HeapRegion* _humongous_start_region; - // True iff the region is in current collection_set. - bool _in_collection_set; // True iff an attempt to evacuate an object in the region failed. bool _evacuation_failed; @@ -487,13 +485,8 @@ return _rem_set; } - // True iff the region is in current collection_set. - bool in_collection_set() const { - return _in_collection_set; - } - void set_in_collection_set(bool b) { - _in_collection_set = b; - } + bool in_collection_set() const; + HeapRegion* next_in_collection_set() { assert(in_collection_set(), "should only invoke on member of CS."); assert(_next_in_special_set == NULL || diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -196,4 +196,8 @@ } } +inline bool HeapRegion::in_collection_set() const { + return G1CollectedHeap::heap()->is_in_cset(this); +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -53,7 +53,7 @@ guarantee(_time_stamps != NULL, "Sanity"); } set_id(which); - set_name("GC task thread#%d (ParallelGC)", which); + set_name("ParGC Thread#%d", which); } GCTaskThread::~GCTaskThread() { diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -34,6 +34,7 @@ #include "memory/resourceArea.hpp" #include "oops/methodCounters.hpp" #include "oops/objArrayKlass.hpp" +#include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/interpreter/interp_masm.hpp --- a/hotspot/src/share/vm/interpreter/interp_masm.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/interpreter/interp_masm.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -27,25 +27,17 @@ #include "asm/macroAssembler.hpp" -#ifdef TARGET_ARCH_x86 +#if defined INTERP_MASM_MD_HPP +# include INTERP_MASM_MD_HPP +#elif defined TARGET_ARCH_x86 # include "interp_masm_x86.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "interp_masm_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "interp_masm_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "interp_masm_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "interp_masm_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "interp_masm_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "interp_masm_aarch64.hpp" #endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/interpreter/templateTable.hpp --- a/hotspot/src/share/vm/interpreter/templateTable.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/interpreter/templateTable.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -341,28 +341,19 @@ static Template* template_for_wide(Bytecodes::Code code) { Bytecodes::wide_check(code); return &_template_table_wide[code]; } // Platform specifics -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined TEMPLATETABLE_MD_HPP +# include TEMPLATETABLE_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "templateTable_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "templateTable_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "templateTable_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "templateTable_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "templateTable_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "templateTable_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "templateTable_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "templateTable_aarch64.hpp" #endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/memory/generation.hpp --- a/hotspot/src/share/vm/memory/generation.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/memory/generation.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,7 +139,7 @@ // GenGrain. // Note: on ARM we add 1 bit for card_table_base to be properly aligned // (we expect its low byte to be zero - see implementation of post_barrier) - LogOfGenGrain = 16 ARM_ONLY(+1), + LogOfGenGrain = 16 ARM32_ONLY(+1), GenGrain = 1 << LogOfGenGrain }; diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/memory/sharedHeap.cpp --- a/hotspot/src/share/vm/memory/sharedHeap.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -68,7 +68,7 @@ } _sh = this; // ch is static, should be set only once. if (UseConcMarkSweepGC || UseG1GC) { - _workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads, + _workers = new FlexibleWorkGang("GC Thread", ParallelGCThreads, /* are_GC_task_threads */true, /* are_ConcurrentGC_threads */false); if (_workers == NULL) { diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/opto/ad.hpp --- a/hotspot/src/share/vm/opto/ad.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/opto/ad.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,28 +25,19 @@ #ifndef SHARE_VM_OPTO_AD_HPP #define SHARE_VM_OPTO_AD_HPP -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined AD_MD_HPP +# include AD_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "adfiles/ad_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "adfiles/ad_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "adfiles/ad_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "adfiles/ad_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "adfiles/ad_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "adfiles/ad_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "adfiles/ad_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "adfiles/ad_aarch64.hpp" #endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/opto/chaitin.cpp --- a/hotspot/src/share/vm/opto/chaitin.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/opto/chaitin.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -847,7 +847,7 @@ case Op_RegD: lrg.set_num_regs(2); // Define platform specific register pressure -#if defined(SPARC) || defined(ARM) +#if defined(SPARC) || defined(ARM32) lrg.set_reg_pressure(2); #elif defined(IA32) if( ireg == Op_RegL ) { diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/opto/optoreg.hpp --- a/hotspot/src/share/vm/opto/optoreg.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/opto/optoreg.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,28 +27,19 @@ // AdGlobals contains c2 specific register handling code as specified // in the .ad files. -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined ADGLOBALS_MD_HPP +# include ADGLOBALS_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "adfiles/adGlobals_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "adfiles/adGlobals_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "adfiles/adGlobals_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "adfiles/adGlobals_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "adfiles/adGlobals_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "adfiles/adGlobals_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "adfiles/adGlobals_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "adfiles/adGlobals_aarch64.hpp" #endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1133,6 +1133,75 @@ VMThread::execute(&force_safepoint_op); WB_END +template +static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) { + assert(value != NULL, "sanity"); + if (method == NULL || name == NULL) { + return false; + } + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, false); + methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid)); + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + const char* flag_name = env->GetStringUTFChars(name, NULL); + bool result = CompilerOracle::has_option_value(mh, flag_name, *value); + env->ReleaseStringUTFChars(name, flag_name); + return result; +} + +WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + bool result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return booleanBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + intx result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return longBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + uintx result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return longBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + double result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return doubleBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + ccstr ccstrResult; + if (GetMethodOption (thread, env, method, name, &ccstrResult)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + jstring result = env->NewStringUTF(ccstrResult); + CHECK_JNI_EXCEPTION_(env, NULL); + return result; + } + return NULL; +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -1333,6 +1402,21 @@ {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, + {CC"getMethodBooleanOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;", + (void*)&WB_GetMethodBooleaneOption}, + {CC"getMethodIntxOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetMethodIntxOption}, + {CC"getMethodUintxOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetMethodUintxOption}, + {CC"getMethodDoubleOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;", + (void*)&WB_GetMethodDoubleOption}, + {CC"getMethodStringOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;", + (void*)&WB_GetMethodStringOption}, }; #undef CC diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -321,6 +321,8 @@ { "UseFastEmptyMethods", JDK_Version::jdk(9), JDK_Version::jdk(10) }, #endif // ZERO { "UseCompilerSafepoints", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "AdaptiveSizePausePolicy", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "ParallelGCRetainPLAB", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { NULL, JDK_Version(0), JDK_Version(0) } }; diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/runtime/globals.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1080,9 +1080,6 @@ notproduct(bool, ProfilerCheckIntervals, false, \ "Collect and print information on spacing of profiler ticks") \ \ - develop(bool, PrintJVMWarnings, false, \ - "Print warnings for unimplemented JVM functions") \ - \ product(bool, PrintWarnings, true, \ "Print JVM warnings to output stream") \ \ @@ -1207,10 +1204,6 @@ "Use pthread-based instead of libthread-based synchronization " \ "(SPARC only)") \ \ - product(bool, AdjustConcurrency, false, \ - "Call thr_setconcurrency at thread creation time to avoid " \ - "LWP starvation on MP systems (for Solaris Only)") \ - \ product(bool, ReduceSignalUsage, false, \ "Reduce the use of OS signals in Java and/or the VM") \ \ @@ -1557,11 +1550,6 @@ product(uintx, ParallelGCBufferWastePct, 10, \ "Wasted fraction of parallel allocation buffer") \ \ - diagnostic(bool, ParallelGCRetainPLAB, false, \ - "Retain parallel allocation buffers across scavenges; " \ - "it is disabled because this currently conflicts with " \ - "parallel card scanning under certain conditions.") \ - \ product(uintx, TargetPLABWastePct, 10, \ "Target wasted space in last buffer as percent of overall " \ "allocation") \ @@ -2101,9 +2089,6 @@ product(uintx, AdaptiveSizeThroughPutPolicy, 0, \ "Policy for changing generation size for throughput goals") \ \ - product(uintx, AdaptiveSizePausePolicy, 0, \ - "Policy for changing generation size for pause goals") \ - \ develop(bool, PSAdjustTenuredGenForMinorPause, false, \ "Adjust tenured generation to achieve a minor pause goal") \ \ diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/runtime/orderAccess.hpp --- a/hotspot/src/share/vm/runtime/orderAccess.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/runtime/orderAccess.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,7 @@ // Memory Access Ordering Model // -// This interface is based on the JSR-133 Cookbook for Compiler Writers -// and on the IA64 memory model. It is the dynamic equivalent of the -// C/C++ volatile specifier. I.e., volatility restricts compile-time -// memory access reordering in a way similar to what we want to occur -// at runtime. +// This interface is based on the JSR-133 Cookbook for Compiler Writers. // // In the following, the terms 'previous', 'subsequent', 'before', // 'after', 'preceding' and 'succeeding' refer to program order. The @@ -41,7 +37,6 @@ // relative to program order, while 'up' and 'above' refer to backward // motion. // -// // We define four primitive memory barrier operations. // // LoadLoad: Load1(s); LoadLoad; Load2 @@ -69,86 +64,88 @@ // operations. Stores before Store1 may *not* float below Load2 and any // subsequent load operations. // +// We define two further barriers: acquire and release. // -// We define two further operations, 'release' and 'acquire'. They are -// mirror images of each other. +// Conceptually, acquire/release semantics form unidirectional and +// asynchronous barriers w.r.t. a synchronizing load(X) and store(X) pair. +// They should always be used in pairs to publish (release store) and +// access (load acquire) some implicitly understood shared data between +// threads in a relatively cheap fashion not requiring storeload. If not +// used in such a pair, it is advised to use a membar instead: +// acquire/release only make sense as pairs. +// +// T1: access_shared_data +// T1: ]release +// T1: (...) +// T1: store(X) // -// Execution by a processor of release makes the effect of all memory -// accesses issued by it previous to the release visible to all -// processors *before* the release completes. The effect of subsequent -// memory accesses issued by it *may* be made visible *before* the -// release. I.e., subsequent memory accesses may float above the -// release, but prior ones may not float below it. +// T2: load(X) +// T2: (...) +// T2: acquire[ +// T2: access_shared_data +// +// It is guaranteed that if T2: load(X) synchronizes with (observes the +// value written by) T1: store(X), then the memory accesses before the T1: +// ]release happen before the memory accesses after the T2: acquire[. +// +// Total Store Order (TSO) machines can be seen as machines issuing a +// release store for each store and a load acquire for each load. Therefore +// there is an inherent resemblence between TSO and acquire/release +// semantics. TSO can be seen as an abstract machine where loads are +// executed immediately when encountered (hence loadload reordering not +// happening) but enqueues stores in a FIFO queue +// for asynchronous serialization (neither storestore or loadstore +// reordering happening). The only reordering happening is storeload due to +// the queue asynchronously serializing stores (yet in order). // -// Execution by a processor of acquire makes the effect of all memory -// accesses issued by it subsequent to the acquire visible to all -// processors *after* the acquire completes. The effect of prior memory -// accesses issued by it *may* be made visible *after* the acquire. -// I.e., prior memory accesses may float below the acquire, but -// subsequent ones may not float above it. +// Acquire/release semantics essentially exploits this asynchronicity: when +// the load(X) acquire[ observes the store of ]release store(X), the +// accesses before the release must have happened before the accesses after +// acquire. +// +// The API offers both stand-alone acquire() and release() as well as bound +// load_acquire() and release_store(). It is guaranteed that these are +// semantically equivalent w.r.t. the defined model. However, since +// stand-alone acquire()/release() does not know which previous +// load/subsequent store is considered the synchronizing load/store, they +// may be more conservative in implementations. We advise using the bound +// variants whenever possible. +// +// Finally, we define a "fence" operation, as a bidirectional barrier. +// It guarantees that any memory access preceding the fence is not +// reordered w.r.t. any memory accesses subsequent to the fence in program +// order. This may be used to prevent sequences of loads from floating up +// above sequences of stores. // -// Finally, we define a 'fence' operation, which conceptually is a -// release combined with an acquire. In the real world these operations -// require one or more machine instructions which can float above and -// below the release or acquire, so we usually can't just issue the -// release-acquire back-to-back. All machines we know of implement some -// sort of memory fence instruction. +// The following table shows the implementations on some architectures: +// +// Constraint x86 sparc TSO ppc +// --------------------------------------------------------------------------- +// fence LoadStore | lock membar #StoreLoad sync +// StoreStore | addl 0,(sp) +// LoadLoad | +// StoreLoad +// +// release LoadStore | lwsync +// StoreStore +// +// acquire LoadLoad | lwsync +// LoadStore +// +// release_store lwsync +// +// +// release_store_fence xchg lwsync +// membar #StoreLoad +// sync // // -// The standalone implementations of release and acquire need an associated -// dummy volatile store or load respectively. To avoid redundant operations, -// we can define the composite operators: 'release_store', 'store_fence' and -// 'load_acquire'. Here's a summary of the machine instructions corresponding -// to each operation. -// -// sparc RMO ia64 x86 -// --------------------------------------------------------------------- -// fence membar #LoadStore | mf lock addl 0,(sp) -// #StoreStore | -// #LoadLoad | -// #StoreLoad -// -// release membar #LoadStore | st.rel [sp]=r0 movl $0, -// #StoreStore -// st %g0,[] -// -// acquire ld [%sp],%g0 ld.acq =[sp] movl (sp), -// membar #LoadLoad | -// #LoadStore -// -// release_store membar #LoadStore | st.rel -// #StoreStore -// st +// load_acquire +// lwsync // -// store_fence st st lock xchg -// fence mf -// -// load_acquire ld ld.acq -// membar #LoadLoad | -// #LoadStore -// -// Using only release_store and load_acquire, we can implement the -// following ordered sequences. -// -// 1. load, load == load_acquire, load -// or load_acquire, load_acquire -// 2. load, store == load, release_store -// or load_acquire, store -// or load_acquire, release_store -// 3. store, store == store, release_store -// or release_store, release_store -// -// These require no membar instructions for sparc-TSO and no extra -// instructions for ia64. -// -// Ordering a load relative to preceding stores requires a store_fence, +// Ordering a load relative to preceding stores requires a StoreLoad, // which implies a membar #StoreLoad between the store and load under -// sparc-TSO. A fence is required by ia64. On x86, we use locked xchg. -// -// 4. store, load == store_fence, load -// -// Use store_fence to make sure all stores done in an 'interesting' -// region are made visible prior to both subsequent loads and stores. +// sparc-TSO. On x86, we use explicitly locked add. // // Conventional usage is to issue a load_acquire for ordered loads. Use // release_store for ordered stores when you care only that prior stores @@ -157,27 +154,19 @@ // release_store_fence to update values like the thread state, where we // don't want the current thread to continue until all our prior memory // accesses (including the new thread state) are visible to other threads. -// +// This is equivalent to the volatile semantics of the Java Memory Model. // -// C++ Volatility +// C++ Volatile Semantics // -// C++ guarantees ordering at operations termed 'sequence points' (defined -// to be volatile accesses and calls to library I/O functions). 'Side -// effects' (defined as volatile accesses, calls to library I/O functions -// and object modification) previous to a sequence point must be visible -// at that sequence point. See the C++ standard, section 1.9, titled -// "Program Execution". This means that all barrier implementations, -// including standalone loadload, storestore, loadstore, storeload, acquire -// and release must include a sequence point, usually via a volatile memory -// access. Other ways to guarantee a sequence point are, e.g., use of -// indirect calls and linux's __asm__ volatile. -// Note: as of 6973570, we have replaced the originally static "dummy" field -// (see above) by a volatile store to the stack. All of the versions of the -// compilers that we currently use (SunStudio, gcc and VC++) respect the -// semantics of volatile here. If you build HotSpot using other -// compilers, you may need to verify that no compiler reordering occurs -// across the sequence point represented by the volatile access. -// +// C++ volatile semantics prevent compiler re-ordering between +// volatile memory accesses. However, reordering between non-volatile +// and volatile memory accesses is in general undefined. For compiler +// reordering constraints taking non-volatile memory accesses into +// consideration, a compiler barrier has to be used instead. Some +// compiler implementations may choose to enforce additional +// constraints beyond those required by the language. Note also that +// both volatile semantics and compiler barrier do not prevent +// hardware reordering. // // os::is_MP Considered Redundant // @@ -240,8 +229,32 @@ // order. If their implementations change such that these assumptions // are violated, a whole lot of code will break. +enum ScopedFenceType { + X_ACQUIRE + , RELEASE_X + , RELEASE_X_FENCE +}; + +template +class ScopedFenceGeneral: public StackObj { + public: + void prefix() {} + void postfix() {} +}; + +template +class ScopedFence : public ScopedFenceGeneral { + void *const _field; + public: + ScopedFence(void *const field) : _field(field) { prefix(); } + ~ScopedFence() { postfix(); } + void prefix() { ScopedFenceGeneral::prefix(); } + void postfix() { ScopedFenceGeneral::postfix(); } +}; + class OrderAccess : AllStatic { public: + // barriers static void loadload(); static void storestore(); static void loadstore(); @@ -280,20 +293,6 @@ static void release_store_ptr(volatile intptr_t* p, intptr_t v); static void release_store_ptr(volatile void* p, void* v); - static void store_fence(jbyte* p, jbyte v); - static void store_fence(jshort* p, jshort v); - static void store_fence(jint* p, jint v); - static void store_fence(jlong* p, jlong v); - static void store_fence(jubyte* p, jubyte v); - static void store_fence(jushort* p, jushort v); - static void store_fence(juint* p, juint v); - static void store_fence(julong* p, julong v); - static void store_fence(jfloat* p, jfloat v); - static void store_fence(jdouble* p, jdouble v); - - static void store_ptr_fence(intptr_t* p, intptr_t v); - static void store_ptr_fence(void** p, void* v); - static void release_store_fence(volatile jbyte* p, jbyte v); static void release_store_fence(volatile jshort* p, jshort v); static void release_store_fence(volatile jint* p, jint v); @@ -313,6 +312,47 @@ // routine if it exists, It should only be used by platforms that // don't have another way to do the inline assembly. static void StubRoutines_fence(); + + // Give platforms a variation point to specialize. + template static T specialized_load_acquire (volatile T* p ); + template static void specialized_release_store (volatile T* p, T v); + template static void specialized_release_store_fence(volatile T* p, T v); + + template + static void ordered_store(volatile FieldType* p, FieldType v); + + template + static FieldType ordered_load(volatile FieldType* p); + + static void store(volatile jbyte* p, jbyte v); + static void store(volatile jshort* p, jshort v); + static void store(volatile jint* p, jint v); + static void store(volatile jlong* p, jlong v); + static void store(volatile jdouble* p, jdouble v); + static void store(volatile jfloat* p, jfloat v); + + static jbyte load (volatile jbyte* p); + static jshort load (volatile jshort* p); + static jint load (volatile jint* p); + static jlong load (volatile jlong* p); + static jdouble load (volatile jdouble* p); + static jfloat load (volatile jfloat* p); + + // The following store_fence methods are deprecated and will be removed + // when all repos conform to the new generalized OrderAccess. + static void store_fence(jbyte* p, jbyte v); + static void store_fence(jshort* p, jshort v); + static void store_fence(jint* p, jint v); + static void store_fence(jlong* p, jlong v); + static void store_fence(jubyte* p, jubyte v); + static void store_fence(jushort* p, jushort v); + static void store_fence(juint* p, juint v); + static void store_fence(julong* p, julong v); + static void store_fence(jfloat* p, jfloat v); + static void store_fence(jdouble* p, jdouble v); + + static void store_ptr_fence(intptr_t* p, intptr_t v); + static void store_ptr_fence(void** p, void* v); }; #endif // SHARE_VM_RUNTIME_ORDERACCESS_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/runtime/orderAccess.inline.hpp --- a/hotspot/src/share/vm/runtime/orderAccess.inline.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/runtime/orderAccess.inline.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,6 +26,7 @@ #ifndef SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP #define SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" // Linux @@ -74,4 +75,92 @@ # include "orderAccess_bsd_zero.inline.hpp" #endif +#ifdef VM_HAS_GENERALIZED_ORDER_ACCESS + +template<> inline void ScopedFenceGeneral::postfix() { OrderAccess::acquire(); } +template<> inline void ScopedFenceGeneral::prefix() { OrderAccess::release(); } +template<> inline void ScopedFenceGeneral::prefix() { OrderAccess::release(); } +template<> inline void ScopedFenceGeneral::postfix() { OrderAccess::fence(); } + + +template +inline void OrderAccess::ordered_store(volatile FieldType* p, FieldType v) { + ScopedFence f((void*)p); + store(p, v); +} + +template +inline FieldType OrderAccess::ordered_load(volatile FieldType* p) { + ScopedFence f((void*)p); + return load(p); +} + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return specialized_load_acquire(p); } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { return specialized_load_acquire(p); } +inline jint OrderAccess::load_acquire(volatile jint* p) { return specialized_load_acquire(p); } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return specialized_load_acquire(p); } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return specialized_load_acquire(p); } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return specialized_load_acquire(p); } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return (jubyte) specialized_load_acquire((volatile jbyte*)p); } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { return (jushort)specialized_load_acquire((volatile jshort*)p); } +inline juint OrderAccess::load_acquire(volatile juint* p) { return (juint) specialized_load_acquire((volatile jint*)p); } +inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong) specialized_load_acquire((volatile jlong*)p); } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)specialized_load_acquire(p); } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*)specialized_load_acquire((volatile intptr_t*)p); } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*)specialized_load_acquire((volatile intptr_t*)p); } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jint* p, jint v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { specialized_release_store((volatile jbyte*) p, (jbyte) v); } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { specialized_release_store((volatile jshort*)p, (jshort)v); } +inline void OrderAccess::release_store(volatile juint* p, juint v) { specialized_release_store((volatile jint*) p, (jint) v); } +inline void OrderAccess::release_store(volatile julong* p, julong v) { specialized_release_store((volatile jlong*) p, (jlong) v); } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { specialized_release_store(p, v); } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { specialized_release_store((volatile intptr_t*)p, (intptr_t)v); } + +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { specialized_release_store_fence((volatile jbyte*) p, (jbyte) v); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { specialized_release_store_fence((volatile jshort*)p, (jshort)v); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { specialized_release_store_fence((volatile jint*) p, (jint) v); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { specialized_release_store_fence((volatile jlong*) p, (jlong) v); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { specialized_release_store_fence(p, v); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { specialized_release_store_fence((volatile intptr_t*)p, (intptr_t)v); } + +// The following methods can be specialized using simple template specialization +// in the platform specific files for optimization purposes. Otherwise the +// generalized variant is used. +template inline T OrderAccess::specialized_load_acquire (volatile T* p) { return ordered_load(p); } +template inline void OrderAccess::specialized_release_store (volatile T* p, T v) { ordered_store(p, v); } +template inline void OrderAccess::specialized_release_store_fence(volatile T* p, T v) { ordered_store(p, v); } + +// Generalized atomic volatile accesses valid in OrderAccess +// All other types can be expressed in terms of these. +inline void OrderAccess::store(volatile jbyte* p, jbyte v) { *p = v; } +inline void OrderAccess::store(volatile jshort* p, jshort v) { *p = v; } +inline void OrderAccess::store(volatile jint* p, jint v) { *p = v; } +inline void OrderAccess::store(volatile jlong* p, jlong v) { Atomic::store(v, p); } +inline void OrderAccess::store(volatile jdouble* p, jdouble v) { Atomic::store(jlong_cast(v), (volatile jlong*)p); } +inline void OrderAccess::store(volatile jfloat* p, jfloat v) { *p = v; } + +inline jbyte OrderAccess::load(volatile jbyte* p) { return *p; } +inline jshort OrderAccess::load(volatile jshort* p) { return *p; } +inline jint OrderAccess::load(volatile jint* p) { return *p; } +inline jlong OrderAccess::load(volatile jlong* p) { return Atomic::load(p); } +inline jdouble OrderAccess::load(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } +inline jfloat OrderAccess::load(volatile jfloat* p) { return *p; } + +#endif // VM_HAS_GENERALIZED_ORDER_ACCESS + #endif // SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,32 +84,22 @@ // Dependencies friend class StubGenerator; -#ifdef TARGET_ARCH_MODEL_x86_32 +#if defined STUBROUTINES_MD_HPP +# include STUBROUTINES_MD_HPP +#elif defined TARGET_ARCH_MODEL_x86_32 # include "stubRoutines_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 +#elif defined TARGET_ARCH_MODEL_x86_64 # include "stubRoutines_x86_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_sparc +#elif defined TARGET_ARCH_MODEL_sparc # include "stubRoutines_sparc.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_zero +#elif defined TARGET_ARCH_MODEL_zero # include "stubRoutines_zero.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_arm -# include "stubRoutines_arm.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_32 -# include "stubRoutines_ppc_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_ppc_64 +#elif defined TARGET_ARCH_MODEL_ppc_64 # include "stubRoutines_ppc_64.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_aarch64 +#elif defined TARGET_ARCH_MODEL_aarch64 # include "stubRoutines_aarch64.hpp" #endif - static jint _verify_oop_count; static address _verify_oop_subroutine_entry; diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/runtime/vm_version.cpp --- a/hotspot/src/share/vm/runtime/vm_version.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/runtime/vm_version.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,18 +187,18 @@ AIX_ONLY("aix") \ BSD_ONLY("bsd") +#ifndef CPU #ifdef ZERO #define CPU ZERO_LIBARCH #else #define CPU IA32_ONLY("x86") \ IA64_ONLY("ia64") \ AMD64_ONLY("amd64") \ - ARM_ONLY("arm") \ - PPC32_ONLY("ppc") \ PPC64_ONLY("ppc64") \ AARCH64_ONLY("aarch64") \ SPARC_ONLY("sparc") #endif // ZERO +#endif const char *Abstract_VM_Version::vm_platform_string() { return OS "-" CPU; @@ -251,12 +251,6 @@ #ifndef FLOAT_ARCH #if defined(__SOFTFP__) #define FLOAT_ARCH_STR "-sflt" - #elif defined(E500V2) - #define FLOAT_ARCH_STR "-e500v2" - #elif defined(ARM) - #define FLOAT_ARCH_STR "-vfp" - #elif defined(PPC32) - #define FLOAT_ARCH_STR "-hflt" #else #define FLOAT_ARCH_STR "" #endif diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/services/mallocSiteTable.cpp --- a/hotspot/src/share/vm/services/mallocSiteTable.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/services/mallocSiteTable.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -135,8 +135,7 @@ */ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx) { - int index = hash_to_index(key.hash()); - assert(index >= 0, err_msg("Negative index %d", index)); + unsigned int index = hash_to_index(key.hash()); *bucket_idx = (size_t)index; *pos_idx = 0; diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/services/mallocSiteTable.hpp --- a/hotspot/src/share/vm/services/mallocSiteTable.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -238,8 +238,7 @@ static MallocSite* malloc_site(size_t bucket_idx, size_t pos_idx); static bool walk(MallocSiteWalker* walker); - static inline int hash_to_index(int hash) { - hash = (hash > 0) ? hash : (-hash); + static inline unsigned int hash_to_index(unsigned int hash) { return (hash % table_size); } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,7 +220,7 @@ #define DEBUG_EXCEPTION ::abort(); -#ifdef ARM +#ifdef ARM32 #ifdef SOLARIS #define BREAKPOINT __asm__ volatile (".long 0xe1200070") #else diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,9 @@ # include +#define __USE_LEGACY_PROTOTYPES__ # include +#undef __USE_LEGACY_PROTOTYPES__ # include # include // for bsd'isms # include diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/utilities/macros.hpp --- a/hotspot/src/share/vm/utilities/macros.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/utilities/macros.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -392,7 +392,6 @@ #define NOT_E500V2(code) code #endif - #ifdef ARM #define ARM_ONLY(code) code #define NOT_ARM(code) @@ -401,6 +400,14 @@ #define NOT_ARM(code) code #endif +#ifdef ARM32 +#define ARM32_ONLY(code) code +#define NOT_ARM32(code) +#else +#define ARM32_ONLY(code) +#define NOT_ARM32(code) code +#endif + #ifdef AARCH64 #define AARCH64_ONLY(code) code #define NOT_AARCH64(code) diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/utilities/nativeCallStack.cpp --- a/hotspot/src/share/vm/utilities/nativeCallStack.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -55,6 +55,7 @@ for (; index < NMT_TrackingStackDepth; index ++) { _stack[index] = NULL; } + _hash_value = 0; } // number of stack frames captured @@ -69,19 +70,16 @@ } // Hash code. Any better algorithm? -int NativeCallStack::hash() const { - long hash_val = _hash_value; +unsigned int NativeCallStack::hash() const { + uintptr_t hash_val = _hash_value; if (hash_val == 0) { - long pc; - int index; - for (index = 0; index < NMT_TrackingStackDepth; index ++) { - pc = (long)_stack[index]; - if (pc == 0) break; - hash_val += pc; + for (int index = 0; index < NMT_TrackingStackDepth; index++) { + if (_stack[index] == NULL) break; + hash_val += (uintptr_t)_stack[index]; } NativeCallStack* p = const_cast(this); - p->_hash_value = (int)(hash_val & 0xFFFFFFFF); + p->_hash_value = (unsigned int)(hash_val & 0xFFFFFFFF); } return _hash_value; } diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/utilities/nativeCallStack.hpp --- a/hotspot/src/share/vm/utilities/nativeCallStack.hpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/utilities/nativeCallStack.hpp Sun Mar 29 09:21:15 2015 -0400 @@ -56,8 +56,8 @@ static const NativeCallStack EMPTY_STACK; private: - address _stack[NMT_TrackingStackDepth]; - int _hash_value; + address _stack[NMT_TrackingStackDepth]; + unsigned int _hash_value; public: NativeCallStack(int toSkip = 0, bool fillStack = false); @@ -89,7 +89,7 @@ } // Hash code. Any better algorithm? - int hash() const; + unsigned int hash() const; void print_on(outputStream* out) const; void print_on(outputStream* out, int indent) const; diff -r f07d88b6243c -r cdecfa325d0c hotspot/src/share/vm/utilities/workgroup.cpp --- a/hotspot/src/share/vm/utilities/workgroup.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/src/share/vm/utilities/workgroup.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -236,7 +236,7 @@ GangWorker::GangWorker(AbstractWorkGang* gang, uint id) { _gang = gang; set_id(id); - set_name("Gang worker#%d (%s)", id, gang->name()); + set_name("%s#%d", gang->name(), id); } void GangWorker::run() { diff -r f07d88b6243c -r cdecfa325d0c hotspot/test/compiler/oracle/GetMethodOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/oracle/GetMethodOptionTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Executable; +import java.util.function.BiFunction; + +import com.oracle.java.testlibrary.Asserts; +import sun.hotspot.WhiteBox; + +/* + * @test + * @bug 8074980 + * @library /testlibrary /../../test/lib + * @build sun.hotspot.WhiteBox com.oracle.java.testlibrary.Asserts GetMethodOptionTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=option,GetMethodOptionTest::test,ccstrlist,MyListOption,_foo,_bar + * -XX:CompileCommand=option,GetMethodOptionTest::test,ccstr,MyStrOption,_foo + * -XX:CompileCommand=option,GetMethodOptionTest::test,bool,MyBoolOption,false + * -XX:CompileCommand=option,GetMethodOptionTest::test,intx,MyIntxOption,-1 + * -XX:CompileCommand=option,GetMethodOptionTest::test,uintx,MyUintxOption,1 + * -XX:CompileCommand=option,GetMethodOptionTest::test,MyFlag + * -XX:CompileCommand=option,GetMethodOptionTest::test,double,MyDoubleOption1,1.123 + * -XX:CompileCommand=option,GetMethodOptionTest.test,double,MyDoubleOption2,1.123 + * -XX:CompileCommand=option,GetMethodOptionTest::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123 + * GetMethodOptionTest + */ + +public class GetMethodOptionTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + public static void main(String[] args) { + Executable test = getMethod("test"); + Executable test2 = getMethod("test2"); + BiFunction getter = WB::getMethodOption; + for (TestCase testCase : TestCase.values()) { + Object expected = testCase.value; + String name = testCase.name(); + Asserts.assertEQ(expected, getter.apply(test, name), + testCase + ": universal getter returns wrong value"); + Asserts.assertEQ(expected, testCase.getter.apply(test, name), + testCase + ": specific getter returns wrong value"); + Asserts.assertEQ(null, getter.apply(test2, name), + testCase + ": universal getter returns value for unused method"); + Asserts.assertEQ(null, testCase.getter.apply(test2, name), + testCase + ": type specific getter returns value for unused method"); + } + } + private static void test() { } + private static void test2() { } + + private static enum TestCase { + MyListOption("_foo _bar", WB::getMethodStringOption), + MyStrOption("_foo", WB::getMethodStringOption), + MyBoolOption(false, WB::getMethodBooleanOption), + MyIntxOption(-1L, WB::getMethodIntxOption), + MyUintxOption(1L, WB::getMethodUintxOption), + MyFlag(true, WB::getMethodBooleanOption), + MyDoubleOption1(1.123d, WB::getMethodDoubleOption), + MyDoubleOption2(1.123d, WB::getMethodDoubleOption), + MyBoolOptionX(false, WB::getMethodBooleanOption), + MyIntxOptionX(-1L, WB::getMethodIntxOption), + MyUintxOptionX(1L, WB::getMethodUintxOption), + MyFlagX(true, WB::getMethodBooleanOption), + MyDoubleOptionX(1.123d, WB::getMethodDoubleOption); + + public final Object value; + public final BiFunction getter; + private TestCase(Object value, BiFunction getter) { + this.value = value; + this.getter = getter; + } + } + + private static Executable getMethod(String name) { + Executable result; + try { + result = GetMethodOptionTest.class.getDeclaredMethod(name); + } catch (NoSuchMethodException | SecurityException e) { + throw new Error("TESTBUG : can't get method " + name, e); + } + return result; + } +} diff -r f07d88b6243c -r cdecfa325d0c hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java --- a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -31,11 +31,13 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -Xmixed * -XX:CompileCommand=compileonly,DeoptimizeFramesTest$TestCaseImpl::method - * -XX:-DeoptimizeRandom -XX:-DeoptimizeALot DeoptimizeFramesTest true + * -XX:+IgnoreUnexpectedVMOptions -XX:-DeoptimizeRandom -XX:-DeoptimizeALot + * DeoptimizeFramesTest true * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -Xmixed * -XX:CompileCommand=compileonly,DeoptimizeFramesTest$TestCaseImpl::method - * -XX:-DeoptimizeRandom -XX:-DeoptimizeALot DeoptimizeFramesTest false + * -XX:+IgnoreUnexpectedVMOptions -XX:-DeoptimizeRandom -XX:-DeoptimizeALot + * DeoptimizeFramesTest false * @summary testing of WB::deoptimizeFrames() */ import java.lang.reflect.Executable; diff -r f07d88b6243c -r cdecfa325d0c hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java --- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Wed Mar 25 15:22:45 2015 +0000 +++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,6 @@ */ /** - * @ignore 8019361 * @test TestDynShrinkHeap * @bug 8016479 * @requires vm.gc=="Parallel" | vm.gc=="null" @@ -35,7 +34,7 @@ import java.lang.management.MemoryUsage; import java.util.ArrayList; import sun.management.ManagementFactoryHelper; -import static com.oracle.java.testlibrary.Asserts.*; +import static com.oracle.java.testlibrary.Asserts.assertLessThan; public class TestDynShrinkHeap { diff -r f07d88b6243c -r cdecfa325d0c jaxp/.hgtags --- a/jaxp/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/jaxp/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -297,3 +297,4 @@ 57b26c883d54f45912bc3885ccad3c6b80960b1f jdk9-b52 d5b5a010a16688f188f5a9247ed873f5100b530c jdk9-b53 542c0c855ad467624cbedf11bff08e44b86b068d jdk9-b54 +2a460ce60ed47081f756f0cc0321d8e9ba7cac17 jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c jaxws/.hgtags --- a/jaxws/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/jaxws/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -300,3 +300,4 @@ 1d1e7704eca9c77ebe6a8705d17ac568801f7a3b jdk9-b52 b8fbe40efa97fe0753076ccc6dfc50747c7877d0 jdk9-b53 83a0cf0e08788c33872e1fe3e87bf9a0d1e59eaa jdk9-b54 +ca481b0492c82cc38fa0e6b746305ed88c26b4fd jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c jdk/.hgtags --- a/jdk/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -297,3 +297,4 @@ 607ea68032cd4a4cf2c7a7a41fcb39602d6a75e2 jdk9-b52 6cb5f5c34009630749a40cefe116d143f0b2583e jdk9-b53 568a62ab7d764d7c74ac1d87387dbe500662b551 jdk9-b54 +d49e247dade61f29f771f09b2105857492241156 jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c jdk/make/Makefile --- a/jdk/make/Makefile Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -# -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# Locate this Makefile -ifeq ($(filter /%, $(lastword $(MAKEFILE_LIST))), ) - makefile_path := $(CURDIR)/$(lastword $(MAKEFILE_LIST)) -else - makefile_path := $(lastword $(MAKEFILE_LIST)) -endif -repo_dir := $(patsubst %/make/Makefile, %, $(makefile_path)) - -# What is the name of this subsystem (langtools, corba, etc)? -subsystem_name := $(notdir $(repo_dir)) - -# Try to locate top-level makefile -top_level_makefile := $(repo_dir)/../Makefile -ifneq ($(wildcard $(top_level_makefile)), ) - $(info Will run $(subsystem_name) target on top-level Makefile) - $(info WARNING: This is a non-recommended way of building!) - $(info ===================================================) -else - $(info Cannot locate top-level Makefile. Is this repo not checked out as part of a complete forest?) - $(error Build from top-level Makefile instead) -endif - -all: - @$(MAKE) -f $(top_level_makefile) $(subsystem_name) diff -r f07d88b6243c -r cdecfa325d0c jdk/make/launcher/Launcher-jdk.pack200.gmk --- a/jdk/make/launcher/Launcher-jdk.pack200.gmk Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk Sun Mar 29 09:21:15 2015 -0400 @@ -79,9 +79,6 @@ CFLAGS_linux := -fPIC, \ CFLAGS_solaris := -KPIC, \ CFLAGS_macosx := -fPIC, \ - DISABLED_WARNINGS_gcc := sign-compare unused-result format-nonliteral \ - format-security parentheses, \ - DISABLED_WARNINGS_microsoft := 4267 4018, \ MAPFILE := $(UNPACK_MAPFILE),\ LDFLAGS := $(UNPACKEXE_ZIPOBJS) \ $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ diff -r f07d88b6243c -r cdecfa325d0c jdk/make/lib/Lib-jdk.pack200.gmk --- a/jdk/make/lib/Lib-jdk.pack200.gmk Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/make/lib/Lib-jdk.pack200.gmk Sun Mar 29 09:21:15 2015 -0400 @@ -40,11 +40,6 @@ -I$(JDK_TOPDIR)/src/jdk.pack200/share/native/common-unpack \ $(LIBJAVA_HEADER_FLAGS), \ CFLAGS_release := -DPRODUCT, \ - DISABLED_WARNINGS_gcc := conversion-null sign-compare format-security \ - format-nonliteral parentheses, \ - DISABLED_WARNINGS_clang := bool-conversion format-security, \ - DISABLED_WARNINGS_solstudio := truncwarn, \ - DISABLED_WARNINGS_microsoft := 4267 4018, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libunpack/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,10 @@ import java.net.URL; import java.net.HttpURLConnection; import java.io.IOException; +import java.security.cert.Certificate; import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; - -import javax.security.cert.X509Certificate; +import javax.net.ssl.SSLPeerUnverifiedException; /** * HTTP URL connection with support for HTTPS-specific features. See @@ -70,7 +70,8 @@ * the server did not authenticate. * @return the server certificate chain */ - public abstract X509Certificate [] getServerCertificateChain(); + public abstract Certificate[] getServerCertificates() + throws SSLPeerUnverifiedException; /** * HostnameVerifier provides a callback mechanism so that diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -187,25 +187,6 @@ return delegate.getServerCertificates(); } - /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * NOTE: This method is not necessary for the version of this class - * implementing javax.net.ssl.HttpsURLConnection, but provided for - * compatibility with the com.sun.net.ssl.HttpsURLConnection version. - */ - public javax.security.cert.X509Certificate[] getServerCertificateChain() { - try { - return delegate.getServerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - // this method does not throw an exception as declared in - // com.sun.net.ssl.HttpsURLConnection. - // Return null for compatibility. - return null; - } - } - /* * Allowable input/output sequences: * [interpreted as POST/PUT] diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/io/ObjectStreamException.java --- a/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java Sun Mar 29 09:21:15 2015 -0400 @@ -38,10 +38,10 @@ /** * Create an ObjectStreamException with the specified argument. * - * @param classname the detailed message for the exception + * @param message the detailed message for the exception */ - protected ObjectStreamException(String classname) { - super(classname); + protected ObjectStreamException(String message) { + super(message); } /** diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Sun Mar 29 09:21:15 2015 -0400 @@ -82,7 +82,7 @@ *
  • a destination for standard output * and standard error. By default, the subprocess writes standard * output and standard error to pipes. Java code can access these pipes - * via the input streams returned by {@link Process#getInputStream()} and + * via the input streams returned by {@link Process#getOutputStream()} and * {@link Process#getErrorStream()}. However, standard output and * standard error may be redirected to other destinations using * {@link #redirectOutput(Redirect) redirectOutput} and @@ -988,14 +988,14 @@ *
  • the standard input to the subprocess was * {@linkplain #redirectInput redirected from a file} * and the security manager's - * {@link SecurityManager#checkRead checkRead} method + * {@link SecurityManager#checkRead(String) checkRead} method * denies read access to the file, or * *
  • the standard output or standard error of the * subprocess was * {@linkplain #redirectOutput redirected to a file} * and the security manager's - * {@link SecurityManager#checkWrite checkWrite} method + * {@link SecurityManager#checkWrite(String) checkWrite} method * denies write access to the file * * diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/net/ProtocolException.java --- a/jdk/src/java.base/share/classes/java/net/ProtocolException.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/net/ProtocolException.java Sun Mar 29 09:21:15 2015 -0400 @@ -42,10 +42,10 @@ * Constructs a new {@code ProtocolException} with the * specified detail message. * - * @param host the detail message. + * @param message the detail message. */ - public ProtocolException(String host) { - super(host); + public ProtocolException(String message) { + super(message); } /** diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/net/UnknownHostException.java --- a/jdk/src/java.base/share/classes/java/net/UnknownHostException.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/net/UnknownHostException.java Sun Mar 29 09:21:15 2015 -0400 @@ -41,10 +41,10 @@ * Constructs a new {@code UnknownHostException} with the * specified detail message. * - * @param host the detail message. + * @param message the detail message. */ - public UnknownHostException(String host) { - super(host); + public UnknownHostException(String message) { + super(message); } /** diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/Date.java --- a/jdk/src/java.base/share/classes/java/util/Date.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/Date.java Sun Mar 29 09:21:15 2015 -0400 @@ -1317,6 +1317,7 @@ private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); s.writeLong(getTimeImpl()); } @@ -1326,6 +1327,7 @@ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); fastTime = s.readLong(); } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/Optional.java --- a/jdk/src/java.base/share/classes/java/util/Optional.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/Optional.java Sun Mar 29 09:21:15 2015 -0400 @@ -346,7 +346,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/OptionalDouble.java --- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Sun Mar 29 09:21:15 2015 -0400 @@ -244,7 +244,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/OptionalInt.java --- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java Sun Mar 29 09:21:15 2015 -0400 @@ -244,7 +244,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/OptionalLong.java --- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java Sun Mar 29 09:21:15 2015 -0400 @@ -244,7 +244,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/Properties.java --- a/jdk/src/java.base/share/classes/java/util/Properties.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/Properties.java Sun Mar 29 09:21:15 2015 -0400 @@ -309,7 +309,7 @@ * input stream. * @throws IllegalArgumentException if a malformed Unicode escape * appears in the input. - * @throws NullPointerException if {@code reader} is null. + * @throws NullPointerException if {@code reader} is null. * @since 1.6 */ public synchronized void load(Reader reader) throws IOException { @@ -335,7 +335,7 @@ * input stream. * @throws IllegalArgumentException if the input stream contains a * malformed Unicode escape sequence. - * @throws NullPointerException if {@code inStream} is null. + * @throws NullPointerException if {@code inStream} is null. * @since 1.2 */ public synchronized void load(InputStream inStream) throws IOException { diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java --- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -380,60 +380,6 @@ } /** - * Prepare the pipeline for a parallel execution. As the pipeline is built, - * the flags and depth indicators are set up for a sequential execution. - * If the execution is parallel, and there are any stateful operations, then - * some of these need to be adjusted, as well as adjusting for flags from - * the terminal operation (such as back-propagating UNORDERED). - * Need not be called for a sequential execution. - * - * @param terminalFlags Operation flags for the terminal operation - */ - private void parallelPrepare(int terminalFlags) { - @SuppressWarnings("rawtypes") - AbstractPipeline backPropagationHead = sourceStage; - if (sourceStage.sourceAnyStateful) { - int depth = 1; - for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage; - p != null; - u = p, p = p.nextStage) { - int thisOpFlags = p.sourceOrOpFlags; - if (p.opIsStateful()) { - // If the stateful operation is a short-circuit operation - // then move the back propagation head forwards - // NOTE: there are no size-injecting ops - if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) { - backPropagationHead = p; - // Clear the short circuit flag for next pipeline stage - // This stage encapsulates short-circuiting, the next - // stage may not have any short-circuit operations, and - // if so spliterator.forEachRemaining should be used - // for traversal - thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT; - } - - depth = 0; - // The following injects size, it is equivalent to: - // StreamOpFlag.combineOpFlags(StreamOpFlag.IS_SIZED, p.combinedFlags); - thisOpFlags = (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED; - } - p.depth = depth++; - p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags); - } - } - - // Apply the upstream terminal flags - if (terminalFlags != 0) { - int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; - for ( @SuppressWarnings("rawtypes") AbstractPipeline p = backPropagationHead; p.nextStage != null; p = p.nextStage) { - p.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, p.combinedFlags); - } - - combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags); - } - } - - /** * Get the source spliterator for this pipeline stage. For a sequential or * stateless parallel pipeline, this is the source spliterator. For a * stateful parallel pipeline, this is a spliterator describing the results @@ -456,24 +402,70 @@ throw new IllegalStateException(MSG_CONSUMED); } - if (isParallel()) { - // @@@ Merge parallelPrepare with the loop below and use the - // spliterator characteristics to determine if SIZED - // should be injected - parallelPrepare(terminalFlags); + boolean hasTerminalFlags = terminalFlags != 0; + if (isParallel() && sourceStage.sourceAnyStateful) { + // Adjust pipeline stages if there are stateful ops, + // and find the last short circuiting op, if any, that + // defines the head stage for back-propagation of terminal flags + @SuppressWarnings("rawtypes") + AbstractPipeline backPropagationHead = sourceStage; + int depth = 1; + for (@SuppressWarnings("rawtypes") AbstractPipeline p = sourceStage.nextStage; + p != null; + p = p.nextStage) { + if (p.opIsStateful()) { + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(p.sourceOrOpFlags)) { + // If the stateful operation is a short-circuit operation + // then move the back propagation head forwards + // NOTE: there are no size-injecting ops + backPropagationHead = p; + } + + depth = 0; + } + p.depth = depth++; + } // Adapt the source spliterator, evaluating each stateful op // in the pipeline up to and including this pipeline stage - for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; + // Flags for each pipeline stage are adjusted accordingly + boolean backPropagate = false; + int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; + for (@SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; u != e; u = p, p = p.nextStage) { + if (hasTerminalFlags && + (backPropagate || (backPropagate = (u == backPropagationHead)))) { + // Back-propagate flags from the terminal operation + u.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, u.combinedFlags); + } + + int thisOpFlags = p.sourceOrOpFlags; if (p.opIsStateful()) { + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) { + // Clear the short circuit flag for next pipeline stage + // This stage encapsulates short-circuiting, the next + // stage may not have any short-circuit operations, and + // if so spliterator.forEachRemaining should be used + // for traversal + thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT; + } + spliterator = p.opEvaluateParallelLazy(u, spliterator); + + // Inject or clear SIZED on the source pipeline stage + // based on the stage's spliterator + thisOpFlags = spliterator.hasCharacteristics(Spliterator.SIZED) + ? (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED + : (thisOpFlags & ~StreamOpFlag.IS_SIZED) | StreamOpFlag.NOT_SIZED; } + p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags); } } - else if (terminalFlags != 0) { + + if (hasTerminalFlags) { + // Apply flags from the terminal operation to last pipeline stage combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags); } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java --- a/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java Sun Mar 29 09:21:15 2015 -0400 @@ -264,6 +264,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -433,6 +438,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -602,6 +612,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -771,6 +786,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/misc/Unsafe.java --- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java Sun Mar 29 09:21:15 2015 -0400 @@ -631,6 +631,10 @@ /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. + * + *

    This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * * @return {@code true} if successful */ public final native boolean compareAndSwapObject(Object o, long offset, @@ -640,6 +644,10 @@ /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. + * + *

    This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * * @return {@code true} if successful */ public final native boolean compareAndSwapInt(Object o, long offset, @@ -649,6 +657,10 @@ /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. + * + *

    This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * * @return {@code true} if successful */ public final native boolean compareAndSwapLong(Object o, long offset, diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java Sun Mar 29 09:21:15 2015 -0400 @@ -262,27 +262,6 @@ } /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - public javax.security.cert.X509Certificate[] getServerCertificateChain() - throws SSLPeerUnverifiedException { - if (cachedResponse != null) { - throw new UnsupportedOperationException("this method is not supported when using cache"); - } - if (http == null) { - throw new IllegalStateException("connection not yet open"); - } else { - return ((HttpsClient)http).getServerCertificateChain(); - } - } - - /** * Returns the server's principal, or throws SSLPeerUnverifiedException * if the server did not authenticate. */ diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Sun Mar 29 09:21:15 2015 -0400 @@ -697,21 +697,6 @@ } /** - * Returns the X.509 certificate chain with which the server - * authenticated itself, or null if the server did not authenticate. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - javax.security.cert.X509Certificate [] getServerCertificateChain() - throws SSLPeerUnverifiedException - { - return session.getPeerCertificateChain(); - } - - /** * Returns the principal with which the server authenticated * itself, or throw a SSLPeerUnverifiedException if the * server did not authenticate. diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -198,30 +198,6 @@ } /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * NOTE: This method is not necessary for the version of this class - * implementing javax.net.ssl.HttpsURLConnection, but provided for - * compatibility with the com.sun.net.ssl.HttpsURLConnection version. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - public javax.security.cert.X509Certificate[] getServerCertificateChain() { - try { - return delegate.getServerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - // this method does not throw an exception as declared in - // com.sun.net.ssl.HttpsURLConnection. - // Return null for compatibility. - return null; - } - } - - /** * Returns the principal with which the server authenticated itself, * or throw a SSLPeerUnverifiedException if the server did not authenticate. */ diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java --- a/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Sun Mar 29 09:21:15 2015 -0400 @@ -290,8 +290,9 @@ throw new SignatureException("Cert request was not signed"); + byte[] CRLF = new byte[] {'\r', '\n'}; out.println("-----BEGIN NEW CERTIFICATE REQUEST-----"); - out.println(Base64.getMimeEncoder().encodeToString(encoded)); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(encoded)); out.println("-----END NEW CERTIFICATE REQUEST-----"); } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java --- a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java Sun Mar 29 09:21:15 2015 -0400 @@ -28,6 +28,8 @@ import java.io.*; import java.util.*; import java.security.cert.*; + +import sun.security.util.Pem; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.pkcs.PKCS7; @@ -633,7 +635,7 @@ checkHeaderFooter(header.toString(), footer.toString()); - return Base64.getMimeDecoder().decode(new String(data, 0, pos)); + return Pem.decode(new String(data, 0, pos)); } } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Sun Mar 29 09:21:15 2015 -0400 @@ -80,6 +80,7 @@ import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; import sun.security.util.DerValue; +import sun.security.util.Pem; import sun.security.x509.*; import static java.security.KeyStore.*; @@ -100,6 +101,8 @@ */ public final class Main { + private static final byte[] CRLF = new byte[] {'\r', '\n'}; + private boolean debug = false; private Command command = null; private String sigAlgName = null; @@ -1266,7 +1269,7 @@ sb.append(s); } } - byte[] rawReq = Base64.getMimeDecoder().decode(new String(sb)); + byte[] rawReq = Pem.decode(new String(sb)); PKCS10 req = new PKCS10(rawReq); info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo())); @@ -1343,7 +1346,7 @@ crl.sign(privateKey, sigAlgName); if (rfc) { out.println("-----BEGIN X509 CRL-----"); - out.println(Base64.getMimeEncoder().encodeToString(crl.getEncodedInternal())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal())); out.println("-----END X509 CRL-----"); } else { out.write(crl.getEncodedInternal()); @@ -2304,7 +2307,7 @@ if (rfc) { X509CRL xcrl = (X509CRL)crl; out.println("-----BEGIN X509 CRL-----"); - out.println(Base64.getMimeEncoder().encodeToString(xcrl.getEncoded())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded())); out.println("-----END X509 CRL-----"); } else { out.println(crl.toString()); @@ -2331,7 +2334,7 @@ sb.append(s); } } - PKCS10 req = new PKCS10(Base64.getMimeDecoder().decode(new String(sb))); + PKCS10 req = new PKCS10(Pem.decode(new String(sb))); PublicKey pkey = req.getSubjectPublicKeyInfo(); out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."), @@ -3115,7 +3118,7 @@ { if (rfc) { out.println(X509Factory.BEGIN_CERT); - out.println(Base64.getMimeEncoder().encodeToString(cert.getEncoded())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(cert.getEncoded())); out.println(X509Factory.END_CERT); } else { out.write(cert.getEncoded()); // binary diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/security/util/Pem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/util/Pem.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.io.IOException; +import java.util.Base64; + +/** + * The Length interface defines the length of an object + */ +public class Pem { + + /** + * Decodes a PEM-encoded block. + * + * @param input the input string, according to RFC 1421, can only contain + * characters in the base-64 alphabet and whitespaces. + * @return the decoded bytes + * @throws java.io.IOException if input is invalid + */ + public static byte[] decode(String input) throws IOException { + byte[] src = input.replaceAll("\\s+", "").getBytes(); + try { + return Base64.getDecoder().decode(src); + } catch (IllegalArgumentException e) { + throw new IOException(e); + } + } +} diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java --- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -271,7 +271,7 @@ der = new DerValue(decstream.toByteArray()); break; } else { - decstream.write(Base64.getMimeDecoder().decode(line)); + decstream.write(Pem.decode(line)); } } } catch (IOException ioe2) { diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/native/libjli/manifest_info.h --- a/jdk/src/java.base/share/native/libjli/manifest_info.h Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/native/libjli/manifest_info.h Sun Mar 29 09:21:15 2015 -0400 @@ -109,6 +109,8 @@ /* * Macros for getting end of central directory header (END) fields */ +#define ENDNMD(b) SH(b, 4) /* number of this disk */ +#define ENDDSK(b) SH(b, 6) /* disk number of start */ #define ENDSUB(b) SH(b, 8) /* number of entries on this disk */ #define ENDTOT(b) SH(b, 10) /* total number of entries */ #define ENDSIZ(b) LG(b, 12) /* central directory size */ diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/share/native/libjli/parse_manifest.c --- a/jdk/src/java.base/share/native/libjli/parse_manifest.c Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/share/native/libjli/parse_manifest.c Sun Mar 29 09:21:15 2015 -0400 @@ -111,52 +111,127 @@ return (NULL); } -static jboolean zip64_present = JNI_FALSE; +/* + * Implementation notes: + * + * This is a zip format reader for seekable files, that tolerates + * leading and trailing garbage, and tolerates having had internal + * offsets adjusted for leading garbage (as with Info-Zip's zip -A). + * + * We find the end header by scanning backwards from the end of the + * file for the end signature. This may fail in the presence of + * trailing garbage or a ZIP file comment that contains binary data. + * Similarly, the ZIP64 end header may need to be located by scanning + * backwards from the end header. It may be misidentified, but this + * is very unlikely to happen in practice without adversarial input. + * + * The zip file format is documented at: + * https://www.pkware.com/documents/casestudies/APPNOTE.TXT + * + * TODO: more informative error messages + */ + +/** Reads count bytes from fd at position pos into given buffer. */ +static jboolean +readAt(int fd, jlong pos, size_t count, void *buf) { + return (pos >= 0 + && JLI_Lseek(fd, pos, SEEK_SET) == pos + && read(fd, buf, count) == (jlong) count); +} + /* - * Checks to see if we have ZIP64 archive, and save - * the check for later use + * Tells whether given header values (obtained from either ZIP64 or + * non-ZIP64 header) appear to be correct, by checking the first LOC + * and CEN headers. */ -static int -haveZIP64(Byte *p) { - jlong cenlen, cenoff, centot; - cenlen = ENDSIZ(p); - cenoff = ENDOFF(p); - centot = ENDTOT(p); - zip64_present = (cenlen == ZIP64_MAGICVAL || - cenoff == ZIP64_MAGICVAL || - centot == ZIP64_MAGICCOUNT); - return zip64_present; -} - -static jlong -find_end64(int fd, Byte *ep, jlong pos) -{ - jlong end64pos; - jlong bytes; - if ((end64pos = JLI_Lseek(fd, pos - ZIP64_LOCHDR, SEEK_SET)) < (jlong)0) - return -1; - if ((bytes = read(fd, ep, ZIP64_LOCHDR)) < 0) - return -1; - if (ZIP64_LOCSIG_AT(ep)) - return end64pos; - return -1; +static jboolean +is_valid_end_header(int fd, jlong endpos, + jlong censiz, jlong cenoff, jlong entries) { + Byte cenhdr[CENHDR]; + Byte lochdr[LOCHDR]; + // Expected offset of the first central directory header + jlong censtart = endpos - censiz; + // Expected position within the file that offsets are relative to + jlong base_offset = endpos - (censiz + cenoff); + return censtart >= 0 && cenoff >= 0 && + (censiz == 0 || + // Validate first CEN and LOC header signatures. + // Central directory must come directly before the end header. + (readAt(fd, censtart, CENHDR, cenhdr) + && CENSIG_AT(cenhdr) + && readAt(fd, base_offset + CENOFF(cenhdr), LOCHDR, lochdr) + && LOCSIG_AT(lochdr) + && CENNAM(cenhdr) == LOCNAM(lochdr))); } /* - * A very little used routine to handle the case that zip file has - * a comment at the end. Believe it or not, the only way to find the - * END record is to walk backwards, byte by bloody byte looking for - * the END record signature. + * Tells whether p appears to be pointing at a valid ZIP64 end header. + * Values censiz, cenoff, and entries are the corresponding values + * from the non-ZIP64 end header. We perform extra checks to avoid + * misidentifying data from the last entry as a ZIP64 end header. + */ +static jboolean +is_zip64_endhdr(int fd, const Byte *p, jlong end64pos, + jlong censiz, jlong cenoff, jlong entries) { + if (ZIP64_ENDSIG_AT(p)) { + jlong censiz64 = ZIP64_ENDSIZ(p); + jlong cenoff64 = ZIP64_ENDOFF(p); + jlong entries64 = ZIP64_ENDTOT(p); + return (censiz64 == censiz || censiz == ZIP64_MAGICVAL) + && (cenoff64 == cenoff || cenoff == ZIP64_MAGICVAL) + && (entries64 == entries || entries == ZIP64_MAGICCOUNT) + && is_valid_end_header(fd, end64pos, censiz64, cenoff64, entries64); + } + return JNI_FALSE; +} + +/* + * Given a non-ZIP64 end header located at endhdr and endpos, look for + * an adjacent ZIP64 end header, finding the base offset and censtart + * from the ZIP64 header if available, else from the non-ZIP64 header. + * @return 0 if successful, -1 in case of failure + */ +static int +find_positions64(int fd, const Byte * const endhdr, const jlong endpos, + jlong* base_offset, jlong* censtart) +{ + jlong censiz = ENDSIZ(endhdr); + jlong cenoff = ENDOFF(endhdr); + jlong entries = ENDTOT(endhdr); + jlong end64pos; + Byte buf[ZIP64_ENDHDR + ZIP64_LOCHDR]; + if (censiz + cenoff != endpos + && (end64pos = endpos - sizeof(buf)) >= (jlong)0 + && readAt(fd, end64pos, sizeof(buf), buf) + && ZIP64_LOCSIG_AT(buf + ZIP64_ENDHDR) + && (jlong) ZIP64_LOCDSK(buf + ZIP64_ENDHDR) == ENDDSK(endhdr) + && (is_zip64_endhdr(fd, buf, end64pos, censiz, cenoff, entries) + || // A variable sized "zip64 extensible data sector" ? + ((end64pos = ZIP64_LOCOFF(buf + ZIP64_ENDHDR)) >= (jlong)0 + && readAt(fd, end64pos, ZIP64_ENDHDR, buf) + && is_zip64_endhdr(fd, buf, end64pos, censiz, cenoff, entries))) + ) { + *censtart = end64pos - ZIP64_ENDSIZ(buf); + *base_offset = *censtart - ZIP64_ENDOFF(buf); + } else { + if (!is_valid_end_header(fd, endpos, censiz, cenoff, entries)) + return -1; + *censtart = endpos - censiz; + *base_offset = *censtart - cenoff; + } + return 0; +} + +/* + * Finds the base offset and censtart of the zip file. * - * fd: File descriptor of the jar file. - * eb: Pointer to a buffer to receive a copy of the END header. - * - * Returns the offset of the END record in the file on success, - * -1 on failure. + * @param fd file descriptor of the jar file + * @param eb scratch buffer + * @return 0 if successful, -1 in case of failure */ -static jlong -find_end(int fd, Byte *eb) +static int +find_positions(int fd, Byte *eb, jlong* base_offset, jlong* censtart) { jlong len; jlong pos; @@ -177,7 +252,7 @@ if ((bytes = read(fd, eb, ENDHDR)) < 0) return (-1); if (ENDSIG_AT(eb)) { - return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; + return find_positions64(fd, eb, pos, base_offset, censtart); } /* @@ -208,7 +283,7 @@ (void) memcpy(eb, cp, ENDHDR); free(buffer); pos = flen - (endpos - cp); - return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; + return find_positions64(fd, eb, pos, base_offset, censtart); } free(buffer); return (-1); @@ -218,82 +293,6 @@ #define MINREAD 1024 /* - * Computes and positions at the start of the CEN header, ie. the central - * directory, this will also return the offset if there is a zip file comment - * at the end of the archive, for most cases this would be 0. - */ -static jlong -compute_cen(int fd, Byte *bp) -{ - int bytes; - Byte *p; - jlong base_offset; - jlong offset; - char buffer[MINREAD]; - p = (Byte*) buffer; - /* - * Read the END Header, which is the starting point for ZIP files. - * (Clearly designed to make writing a zip file easier than reading - * one. Now isn't that precious...) - */ - if ((base_offset = find_end(fd, bp)) == -1) { - return (-1); - } - p = bp; - /* - * There is a historical, but undocumented, ability to allow for - * additional "stuff" to be prepended to the zip/jar file. It seems - * that this has been used to prepend an actual java launcher - * executable to the jar on Windows. Although this is just another - * form of statically linking a small piece of the JVM to the - * application, we choose to continue to support it. Note that no - * guarantees have been made (or should be made) to the customer that - * this will continue to work. - * - * Therefore, calculate the base offset of the zip file (within the - * expanded file) by assuming that the central directory is followed - * immediately by the end record. - */ - if (zip64_present) { - if ((offset = ZIP64_LOCOFF(p)) < (jlong)0) { - return -1; - } - if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong) 0) { - return (-1); - } - if ((bytes = read(fd, buffer, MINREAD)) < 0) { - return (-1); - } - if (!ZIP64_ENDSIG_AT(buffer)) { - return -1; - } - if ((offset = ZIP64_ENDOFF(buffer)) < (jlong)0) { - return -1; - } - if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong)0) { - return (-1); - } - p = (Byte*) buffer; - base_offset = base_offset - ZIP64_ENDSIZ(p) - ZIP64_ENDOFF(p) - ZIP64_ENDHDR; - } else { - base_offset = base_offset - ENDSIZ(p) - ENDOFF(p); - /* - * The END Header indicates the start of the Central Directory - * Headers. Remember that the desired Central Directory Header (CEN) - * will almost always be the second one and the first one is a small - * directory entry ("META-INF/"). Keep the code optimized for - * that case. - * - * Seek to the beginning of the Central Directory. - */ - if (JLI_Lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (jlong) 0) { - return (-1); - } - } - return base_offset; -} - -/* * Locate the manifest file with the zip/jar file. * * fd: File descriptor of the jar file. @@ -327,7 +326,23 @@ int res; int entry_size; int read_size; + + /* + * The (imaginary) position within the file relative to which + * offsets within the zip file refer. This is usually the + * location of the first local header (the start of the zip data) + * (which in turn is usually 0), but if the zip file has content + * prepended, then it will be either 0 or the length of the + * prepended content, depending on whether or not internal offsets + * have been adjusted (via e.g. zip -A). May be negative if + * content is prepended, zip -A is run, then the prefix is + * detached! + */ jlong base_offset; + + /** The position within the file of the start of the central directory. */ + jlong censtart; + Byte *p; Byte *bp; Byte *buffer; @@ -338,9 +353,11 @@ } bp = buffer; - base_offset = compute_cen(fd, bp); - if (base_offset == -1) { - free(buffer); + + if (find_positions(fd, bp, &base_offset, &censtart) == -1) { + return -1; + } + if (JLI_Lseek(fd, censtart, SEEK_SET) < (jlong) 0) { return -1; } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -496,12 +496,11 @@ public synchronized boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (hasExited) return true; if (timeout <= 0) return false; - long remainingNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + remainingNanos; - do { // Round up to next millisecond wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L)); diff -r f07d88b6243c -r cdecfa325d0c jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java --- a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -458,12 +458,11 @@ public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; if (timeout <= 0) return false; - long remainingNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + remainingNanos ; - do { // Round up to next millisecond long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L); diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -142,7 +142,7 @@ new String[] { "Jan", // abb january "Feb", // abb february - "Mrz", // abb march + "M\u00e4r", // abb march "Apr", // abb april "Mai", // abb may "Jun", // abb june diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/common-unpack/bytes.h --- a/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h Sun Mar 29 09:21:15 2015 -0400 @@ -63,7 +63,7 @@ bytes res; res.ptr = ptr + beg; res.len = end - beg; - assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit()-1)); + assert(res.len == 0 || (inBounds(res.ptr) && inBounds(res.limit()-1))); return res; } // building C strings inside byte buffers: diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -225,9 +225,9 @@ } #ifdef PRODUCT - char* string() { return 0; } + const char* string() { return NULL; } #else - char* string(); // see far below + const char* string(); // see far below #endif }; @@ -718,13 +718,13 @@ // Now we can size the whole archive. // Read everything else into a mega-buffer. rp = hdr.rp; - int header_size_0 = (int)(rp - input.base()); // used-up header (4byte + 3int) - int header_size_1 = (int)(rplimit - rp); // buffered unused initial fragment - int header_size = header_size_0+header_size_1; + size_t header_size_0 = (rp - input.base()); // used-up header (4byte + 3int) + size_t header_size_1 = (rplimit - rp); // buffered unused initial fragment + size_t header_size = header_size_0 + header_size_1; unsized_bytes_read = header_size_0; CHECK; if (foreign_buf) { - if (archive_size > (size_t)header_size_1) { + if (archive_size > header_size_1) { abort("EOF reading fixed input buffer"); return; } @@ -738,7 +738,7 @@ return; } input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)), - (size_t) header_size_0 + archive_size); + header_size_0 + archive_size); CHECK; assert(input.limit()[0] == 0); // Move all the bytes we read initially into the real buffer. @@ -961,13 +961,13 @@ nentries = next_entry; // place a limit on future CP growth: - int generous = 0; + size_t generous = 0; generous = add_size(generous, u->ic_count); // implicit name generous = add_size(generous, u->ic_count); // outer generous = add_size(generous, u->ic_count); // outer.utf8 generous = add_size(generous, 40); // WKUs, misc generous = add_size(generous, u->class_count); // implicit SourceFile strings - maxentries = add_size(nentries, generous); + maxentries = (uint)add_size(nentries, generous); // Note that this CP does not include "empty" entries // for longs and doubles. Those are introduced when @@ -985,8 +985,9 @@ } // Initialize *all* our entries once - for (int i = 0 ; i < maxentries ; i++) + for (uint i = 0 ; i < maxentries ; i++) { entries[i].outputIndex = REQUESTED_NONE; + } initGroupIndexes(); // Initialize hashTab to a generous power-of-two size. @@ -3680,21 +3681,22 @@ unpacker* debug_u; -static bytes& getbuf(int len) { // for debugging only! +static bytes& getbuf(size_t len) { // for debugging only! static int bn = 0; static bytes bufs[8]; bytes& buf = bufs[bn++ & 7]; - while ((int)buf.len < len+10) + while (buf.len < len + 10) { buf.realloc(buf.len ? buf.len * 2 : 1000); + } buf.ptr[0] = 0; // for the sake of strcat return buf; } -char* entry::string() { +const char* entry::string() { bytes buf; switch (tag) { case CONSTANT_None: - return (char*)""; + return ""; case CONSTANT_Signature: if (value.b.ptr == null) return ref(0)->string(); @@ -3714,26 +3716,28 @@ break; default: if (nrefs == 0) { - buf = getbuf(20); - sprintf((char*)buf.ptr, TAG_NAME[tag]); + return TAG_NAME[tag]; } else if (nrefs == 1) { return refs[0]->string(); } else { - char* s1 = refs[0]->string(); - char* s2 = refs[1]->string(); - buf = getbuf((int)strlen(s1) + 1 + (int)strlen(s2) + 4 + 1); + const char* s1 = refs[0]->string(); + const char* s2 = refs[1]->string(); + buf = getbuf(strlen(s1) + 1 + strlen(s2) + 4 + 1); buf.strcat(s1).strcat(" ").strcat(s2); if (nrefs > 2) buf.strcat(" ..."); } } - return (char*)buf.ptr; + return (const char*)buf.ptr; } void print_cp_entry(int i) { entry& e = debug_u->cp.entries[i]; - char buf[30]; - sprintf(buf, ((uint)e.tag < CONSTANT_Limit)? TAG_NAME[e.tag]: "%d", e.tag); - printf(" %d\t%s %s\n", i, buf, e.string()); + + if ((uint)e.tag < CONSTANT_Limit) { + printf(" %d\t%s %s\n", i, TAG_NAME[e.tag], e.string()); + } else { + printf(" %d\t%d %s\n", i, e.tag, e.string()); + } } void print_cp_entries(int beg, int end) { diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/common-unpack/unpack.h --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h Sun Mar 29 09:21:15 2015 -0400 @@ -210,7 +210,7 @@ byte* rp; // read pointer (< rplimit <= input.limit()) byte* rplimit; // how much of the input block has been read? julong bytes_read; - int unsized_bytes_read; + size_t unsized_bytes_read; // callback to read at least one byte, up to available input typedef jlong (*read_input_fn_t)(unpacker* self, void* buf, jlong minlen, jlong maxlen); diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp --- a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -81,7 +81,7 @@ int assert_failed(const char* p) { char message[1<<12]; sprintf(message, "@assert failed: %s\n", p); - fprintf(stdout, 1+message); + fprintf(stdout, "%s", 1+message); breakpoint(); unpack_abort(message); return 0; diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp --- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -84,7 +84,7 @@ } // Write data to the ZIP output stream. -void jar::write_data(void* buff, int len) { +void jar::write_data(void* buff, size_t len) { while (len > 0) { int rc = (int)fwrite(buff, 1, len, jarfp); if (rc <= 0) { @@ -323,12 +323,12 @@ // Total number of disks (int) header64[36] = (ushort)SWAP_BYTES(1); header64[37] = 0; - write_data(header64, (int)sizeof(header64)); + write_data(header64, sizeof(header64)); } // Write the End of Central Directory structure. PRINTCR((2, "end-of-directory at %d\n", output_file_offset)); - write_data(header, (int)sizeof(header)); + write_data(header, sizeof(header)); PRINTCR((2, "writing zip comment\n")); // Write the comment. @@ -590,7 +590,7 @@ zstream = NEW(z_stream, 1); u->gzin = this; u->read_input_fn = read_input_via_gzip; - u->gzcrc = crc32(0L, Z_NULL, 0); + u->gzcrc = crc32(0, Z_NULL, 0); } void gunzip::start(int magic) { diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/common-unpack/zip.h --- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.h Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.h Sun Mar 29 09:21:15 2015 -0400 @@ -68,8 +68,8 @@ } // Private Methods - void write_data(void* ptr, int len); - void write_data(bytes& b) { write_data(b.ptr, (int)b.len); } + void write_data(void* ptr, size_t len); + void write_data(bytes& b) { write_data(b.ptr, b.len); } void add_to_jar_directory(const char* fname, bool store, int modtime, int len, int clen, uLong crc); void write_jar_header(const char* fname, bool store, int modtime, diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/libunpack/jni.cpp --- a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -292,7 +292,7 @@ if (uPtr->aborting()) { THROW_IOE(uPtr->get_abort_message()); - return false; + return null; } // We have fetched all the files. @@ -310,7 +310,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) { unpacker* uPtr = get_unpacker(env, pObj, false); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, NULL); + CHECK_EXCEPTION_RETURN_VALUE(uPtr, 0); size_t consumed = uPtr->input_consumed(); free_unpacker(env, pObj, uPtr); return consumed; @@ -320,6 +320,7 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj, jstring pProp, jstring pValue) { unpacker* uPtr = get_unpacker(env, pObj); + CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); CHECK_EXCEPTION_RETURN_VALUE(prop, false); const char* value = env->GetStringUTFChars(pValue, JNI_FALSE); diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.pack200/share/native/unpack200/main.cpp --- a/jdk/src/jdk.pack200/share/native/unpack200/main.cpp Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.pack200/share/native/unpack200/main.cpp Sun Mar 29 09:21:15 2015 -0400 @@ -149,31 +149,28 @@ return progname; } -static const char* usage_lines[] = { - "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n", - "\n", - "Unpacking Options\n", - " -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep (default)\n", - " -r, --remove-pack-file remove input file after unpacking\n", - " -v, --verbose increase program verbosity\n", - " -q, --quiet set verbosity to lowest level\n", - " -l{F}, --log-file={F} output to the given log file, or '-' for standard output (default)\n", - " -?, -h, --help print this message\n", - " -V, --version print program version\n", - " -J{X} Java VM argument (ignored)\n", - null -}; +#define USAGE_HEADER "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n" +#define USAGE_OPTIONS \ + "\n" \ + "Unpacking Options\n" \ + " -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep (default)\n" \ + " -r, --remove-pack-file remove input file after unpacking\n" \ + " -v, --verbose increase program verbosity\n" \ + " -q, --quiet set verbosity to lowest level\n" \ + " -l{F}, --log-file={F} output to the given log file, or '-' for standard output (default)\n" \ + " -?, -h, --help print this message\n" \ + " -V, --version print program version\n" \ + " -J{X} Java VM argument (ignored)\n" static void usage(unpacker* u, const char* progname, bool full = false) { // WinMain does not set argv[0] to the progrname progname = (progname != null) ? nbasename(progname) : "unpack200"; - for (int i = 0; usage_lines[i] != null; i++) { - fprintf(u->errstrm, usage_lines[i], progname); - if (!full) { - fprintf(u->errstrm, - "(For more information, run %s --help .)\n", progname); - break; - } + + fprintf(u->errstrm, USAGE_HEADER, progname); + if (full) { + fprintf(u->errstrm, USAGE_OPTIONS); + } else { + fprintf(u->errstrm, "(For more information, run %s --help .)\n", progname); } } diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java Sun Mar 29 09:21:15 2015 -0400 @@ -184,10 +184,19 @@ return (LG(b, n)) | (LG(b, n + 4) << 32); } - static final long GETSIG(byte[] b) { - return LG(b, 0); + static long getSig(byte[] b, int n) { return LG(b, n); } + + private static boolean pkSigAt(byte[] b, int n, int b1, int b2) { + return b[n] == 'P' & b[n + 1] == 'K' & b[n + 2] == b1 & b[n + 3] == b2; } + static boolean cenSigAt(byte[] b, int n) { return pkSigAt(b, n, 1, 2); } + static boolean locSigAt(byte[] b, int n) { return pkSigAt(b, n, 3, 4); } + static boolean endSigAt(byte[] b, int n) { return pkSigAt(b, n, 5, 6); } + static boolean extSigAt(byte[] b, int n) { return pkSigAt(b, n, 7, 8); } + static boolean end64SigAt(byte[] b, int n) { return pkSigAt(b, n, 6, 6); } + static boolean locator64SigAt(byte[] b, int n) { return pkSigAt(b, n, 6, 7); } + // local file (LOC) header fields static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract diff -r f07d88b6243c -r cdecfa325d0c jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Sun Mar 29 09:21:15 2015 -0400 @@ -1060,7 +1060,7 @@ int pos = 0; int limit = cen.length - ENDHDR; while (pos < limit) { - if (CENSIG(cen, pos) != CENSIG) + if (!cenSigAt(cen, pos)) zerror("invalid CEN header (bad signature)"); int method = CENHOW(cen, pos); int nlen = CENNAM(cen, pos); @@ -1894,7 +1894,7 @@ throws IOException { byte[] cen = zipfs.cen; - if (CENSIG(cen, pos) != CENSIG) + if (!cenSigAt(cen, pos)) zerror("invalid CEN header (bad signature)"); versionMade = CENVEM(cen, pos); version = CENVER(cen, pos); @@ -2057,9 +2057,9 @@ assert (buf.length >= LOCHDR); if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) + if (!locSigAt(buf, 0)) throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); + + Long.toString(getSig(buf, 0), 16)); //startPos = pos; version = LOCVER(buf); flag = LOCFLG(buf); @@ -2289,9 +2289,9 @@ if (zipfs.readFullyAt(buf, 0, buf.length , locoff) != buf.length) throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) + if (!locSigAt(buf, 0)) throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); + + Long.toString(getSig(buf, 0), 16)); int locElen = LOCEXT(buf); if (locElen < 9) // EXTT is at lease 9 bytes diff -r f07d88b6243c -r cdecfa325d0c jdk/test/TEST.ROOT --- a/jdk/test/TEST.ROOT Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/TEST.ROOT Sun Mar 29 09:21:15 2015 -0400 @@ -2,7 +2,7 @@ # It also contains test-suite configuration information. # The list of keywords supported in the entire test suite -keys=2d dnd i18n +keys=2d dnd i18n intermittent # Tests that must run in othervm mode othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation diff -r f07d88b6243c -r cdecfa325d0c jdk/test/TEST.groups --- a/jdk/test/TEST.groups Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/TEST.groups Sun Mar 29 09:21:15 2015 -0400 @@ -38,7 +38,9 @@ :jdk_time \ :jdk_security \ :jdk_text \ - :core_tools + :core_tools \ + :jdk_other \ + :jdk_svc ############################################################################### # diff -r f07d88b6243c -r cdecfa325d0c jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java --- a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -26,6 +26,7 @@ * @run main/othervm LdapTimeoutTest * @bug 7094377 8000487 6176036 7056489 * @summary Timeout tests for ldap + * @key intermittent */ import java.net.Socket; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java --- a/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java Sun Mar 29 09:21:15 2015 -0400 @@ -43,11 +43,16 @@ void test(String[] args) throws IOException { SocketAddress address = null; + String os = System.getProperty("os.name").toLowerCase(); if (!Util.isSCTPSupported()) { out.println("SCTP protocol is not supported"); out.println("Test cannot be run"); return; + } else if (os.startsWith("sunos")) { + out.println("Test not supported on Solaris"); + out.println("Test cannot be run"); + return; } System.out.println("remote address: " + remoteAddress); diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/lang/ProcessBuilder/Basic.java --- a/jdk/test/java/lang/ProcessBuilder/Basic.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Sun Mar 29 09:21:15 2015 -0400 @@ -27,6 +27,7 @@ * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464 + * 8067796 * @summary Basic tests for Process and Environment Variable code * @run main/othervm/timeout=300 Basic * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic @@ -2387,6 +2388,56 @@ } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- + // Check that Process.waitFor(timeout, null) throws NPE. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("sleep"); + final Process p = new ProcessBuilder(childArgs).start(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + // Terminate process and recheck after it exits + p.destroy(); + p.waitFor(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // Check that default implementation of Process.waitFor(timeout, null) throws NPE. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("sleep"); + final Process proc = new ProcessBuilder(childArgs).start(); + final DelegatingProcess p = new DelegatingProcess(proc); + + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + // Terminate process and recheck after it exits + p.destroy(); + p.waitFor(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- // Check the default implementation for // Process.waitFor(long, TimeUnit) //---------------------------------------------------------------- diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java --- a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -41,6 +41,7 @@ * @library /lib/testlibrary/jsr292 /lib/testlibrary/ * @compile CatchExceptionTest.java * @run main/othervm -esa test.java.lang.invoke.MethodHandles.CatchExceptionTest + * @key intermittent */ public class CatchExceptionTest { private static final List> ARGS_CLASSES; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/lang/ref/OOMEInReferenceHandler.java --- a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java Sun Mar 29 09:21:15 2015 -0400 @@ -27,6 +27,7 @@ * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object * @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler * @author peter.levart@gmail.com + * @key intermittent */ import java.lang.ref.*; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java --- a/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -42,6 +42,7 @@ * @test * @bug 8007373 * @summary jdk7 backward compatibility serialization problem + * @key intermittent */ public class Inet6AddressSerializationTest { diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/net/SocketPermission/SocketPermissionTest.java --- a/jdk/test/java/net/SocketPermission/SocketPermissionTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/net/SocketPermission/SocketPermissionTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -27,6 +27,7 @@ * @summary SocketPermission tests for legacy socket types * @library ../../../lib/testlibrary * @run testng/othervm/policy=policy SocketPermissionTest + * @key intermittent */ import java.io.IOException; import java.net.DatagramPacket; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/Buffer/genBasic.sh --- a/jdk/test/java/nio/Buffer/genBasic.sh Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/nio/Buffer/genBasic.sh Sun Mar 29 09:21:15 2015 -0400 @@ -1,7 +1,7 @@ #! /bin/sh # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java +javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java gen() { java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 Basic$2.java diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/Buffer/genCopyDirectMemory.sh --- a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Sun Mar 29 09:21:15 2015 -0400 @@ -1,7 +1,7 @@ #! /bin/sh # -# Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 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 @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java +javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java > Spp.java gen() { java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3CopyDirect$2Memory.java diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/channels/Selector/Wakeup.java diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java --- a/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java Sun Mar 29 09:21:15 2015 -0400 @@ -23,6 +23,7 @@ /* @test * @summary Unit test for server-socket-channel adaptors + * @key intermittent */ import java.io.*; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh --- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh Sun Mar 29 09:21:15 2015 -0400 @@ -24,12 +24,12 @@ # # @test -# @bug 4673940 -# @bug 4930794 +# @bug 4673940 4930794 # @summary Unit tests for inetd feature # # @build StateTest StateTestService EchoTest EchoService CloseTest Launcher Util # @run shell run_tests.sh +# @key intermittent os=`uname -s` diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/file/FileStore/Basic.java --- a/jdk/test/java/nio/file/FileStore/Basic.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/nio/file/FileStore/Basic.java Sun Mar 29 09:21:15 2015 -0400 @@ -25,6 +25,7 @@ * @bug 4313887 6873621 6979526 7006126 7020517 * @summary Unit test for java.nio.file.FileStore * @library .. + * @key intermittent */ import java.nio.file.*; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/nio/file/Files/InterruptCopy.java diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java --- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Sun Mar 29 09:21:15 2015 -0400 @@ -39,6 +39,7 @@ * @build TestLibrary RMID ActivateMe CheckActivateRef_Stub * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=true CheckActivateRef * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=false CheckActivateRef + * @key intermittent */ import java.io.*; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java --- a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java Sun Mar 29 09:21:15 2015 -0400 @@ -38,6 +38,7 @@ * @library ../../testlibrary * @build TestLibrary ReferenceRegistryStub * @run main/othervm InterfaceHash + * @key intermittent */ import java.lang.reflect.Constructor; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java --- a/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java Sun Mar 29 09:21:15 2015 -0400 @@ -31,6 +31,7 @@ * @summary GC'ing objects whilst being exported to RMI should not cause exceptions * @author Neil Richards , * @run main/othervm GcDuringExport + * @key intermittent */ import java.rmi.Remote; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.System.out; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Base64; +import java.util.Enumeration; + +/* + * @test + * @bug 8048618 + * @summary Write different types p12 key store to Check the write related + * APIs. + * @run main WriteP12Test + */ + +public class WriteP12Test { + + private static final String IN_KEYSTORE_TYPE = "jks"; + private static final String IN_KEYSTORE_PRV = "SUN"; + + private static final String IN_KEYSTORE_ENDUSER = "keystoreEU.jks.data"; + private static final String IN_KEYSTORE_CA = "keystoreCA.jks.data"; + private static final String OUT_KEYSTORE = "outKeyStore.p12"; + + private static final String IN_STORE_PASS = "storepass"; + private static final String IN_KEY_PASS = "keypass"; + + private static final String CERT_PATH = System.getProperty("test.src", ".") + + File.separator + "certs" + File.separator + "writeP12" + + File.separator; + + private static final String CA_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIIDFzCCAf8CBD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCV\n" + + "VMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUU\n" + + "UxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAwNTUxMlo\n" + + "XDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEph\n" + + "dmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ\n" + + "1MxMiBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ\n" + + "EAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG00yi9aL\n" + + "SsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7I\n" + + "wRTYYy9clFkeeK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4e\n" + + "f1mUASo6+dea0UZA/FHCuV7O6z3hr5VHlyhJL2/o/8M5tGBTBISODJSnn\n" + + "GNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1XnIkiiXR3\n" + + "tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0\n" + + "dQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhx\n" + + "i18YQc2LPWBDLYTTxoFEazWmYLv1k/JT7Nta1qu1quvxXJ4uV1XHbd9NF\n" + + "AJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhqvO03G0Q\n" + + "imhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Yb\n" + + "k5qe3lviMZPkkSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUr\n" + + "sVOVWh7IBCqC/V7FqUTkmD1IFlzkkinatpl42s1MbhJId2yQkzaeBRc\n" + + "suE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di\n" + + "-----END CERTIFICATE-----"; + private static final String LEAD_CERT = "-----BEGIN CERTIFICATE-----\n" + + "MIICwDCCAaigAwIBAgIEPz7S1jANBgkqhkiG9w0BAQQFADBQMQswCQYDV\n" + + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n" + + "R5IFNRRTEXMBUGA1UEAxMOUEtDUzEyIFRlc3QgQ0EwHhcNMDAwODA5MDc\n" + + "wMDAwWhcNMTAwODA3MDcwMDAwWjBSMQswCQYDVQQGEwJVUzERMA8GA1UE\n" + + "ChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaXR5IFNRRTEZMBcGA1UEA\n" + + "xMQUEtDUzEyIFRlc3QgTGVhZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgY\n" + + "kCgYEAzq9X2USz/WjDhT+jUyZWqB5h4A33tS11YqH5qYvqjTXjcUI6gOp\n" + + "moXMafDG9RHRlIccvp51xLp7Ap3WMrv411lWBttqtZi5c1/DEC1cEM/Sl\n" + + "PCk1r2zFbkJu7QKieXeMcrjZEo6LcBHMwQjIpI+up9cr3VjuyqG/olQkU\n" + + "mXVuS0CAwEAAaMkMCIwDwYDVR0PAQH/BAUDAweAADAPBgNVHRMBAf8EBT\n" + + "ADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBhbuim98TWmtv9vSldRE7RvQ8\n" + + "FlS0TyZVO7kcSNtfCUE4R76J1ElN74Koc5pQnUtduLeQJs2ao/mEcCZsE\n" + + "zVcwI3mSZrSzPhc8s7w5gOQA4TUwVLSSjKgBCaZ7R3+qJ3QeqPJ5O6sFz\n" + + "pvBYkgSa4MWptK41jbmT8cwZQJXFCi8WxFFJ+p97F1Ppm3LgmYmtiUP4M\n" + + "ZQwOBvpTZWXU0WrqFXpzWQx0mg4SX19fZm4nLcJAerCEUphf8ILagtpQM\n" + + "EErT3/jg6mfCdT3Rj055QXPfF4OiRFevPF5a1fZgrCePCukRQZcd7s8K5\n" + + "OBIaryuM0MdFtlzxi6XWeUNpVFFHURcy\n" + + "-----END CERTIFICATE-----"; + private static final String END_CERT = "-----BEGIN CERTIFICATE-----\n" + + "MIICNjCCAZ+gAwIBAgIEPz7WtzANBgkqhkiG9w0BAQQFADBSMQswCQYDV\n" + + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n" + + "R5IFNRRTEZMBcGA1UEAxMQUEtDUzEyIFRlc3QgTGVhZDAeFw0wMDA4MDk\n" + + "wNzAwMDBaFw0xMDA4MDcwNzAwMDBaMFgxCzAJBgNVBAYTAlVTMREwDwYD\n" + + "VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMR8wHQYDV\n" + + "QQDExZQS0NTMTIgVGVzdCBFbmQgVXNlciAxMIGfMA0GCSqGSIb3DQEBAQ\n" + + "UAA4GNADCBiQKBgQDIKomSYomDzH/V63eDQEG7od0DLcnnVZ81pbWhDss\n" + + "8gHV2m8pADdRqdihBmnSQEaMW4D3uZ4sFE1LtkQls6hjd7SdOsG5Y24L8\n" + + "15jot9a2JcB73H8H0VKirrObL5BZdt7BtASPDnYtW4Spt++YjDoJFxyF0\n" + + "HchkavzXaVTlexakwIDAQABoxMwETAPBgNVHQ8BAf8EBQMDB4AAMA0GCS\n" + + "qGSIb3DQEBBAUAA4GBAIFA3JXEmb9AXn3RD7t+Mn6DoyVDIy5jsn6xOKT\n" + + "JV25I0obpDUzgw4QaAMmM0ZvusOmZ2wZNS8MtyTUgdANyakbzn5SdxbTy\n" + + "TLEqQsFbX8UVC38fx5ZM6ExA5YSAvgmXudZpOVC0ATccoZS3JFU8CxSfW\n" + + "+Q3IC2MLh+QTg3hUJ5b\n-----END CERTIFICATE-----"; + + private final Certificate testerCert; + private final Certificate testLeadCert; + private final Certificate caCert; + + WriteP12Test() throws CertificateException { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + caCert = cf.generateCertificate(new ByteArrayInputStream(CA_CERT_STR + .getBytes())); + testLeadCert = cf.generateCertificate(new ByteArrayInputStream( + LEAD_CERT.getBytes())); + testerCert = cf.generateCertificate(new ByteArrayInputStream(END_CERT + .getBytes())); + } + + public static void main(String[] args) throws CertificateException, + UnrecoverableKeyException, KeyStoreException, + NoSuchProviderException, NoSuchAlgorithmException, IOException { + WriteP12Test jstest = new WriteP12Test(); + out.println("test WriteP12CertChain"); + /* + * WriteP12CertChain: This test creates a p12 keystore contains one + * entry with private key and a certificate chains contains three + * certificates in the order of user->lead->ca. This case expects to + * pass. + */ + jstest.test(new Certificate[] { jstest.testerCert, jstest.testLeadCert, + jstest.caCert }, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", + "pass", "pass"); + + /* + * WriteP12CertChainBad: same as WriteP12CertChain but chains order is + * user-ca-lead, the order is wrong so expects to fail. + */ + out.println("test WriteP12CertChainBad"); + try { + jstest.test(new Certificate[] { jstest.testerCert, jstest.caCert, + jstest.testLeadCert }, IN_KEYSTORE_ENDUSER, + "pkcs12testenduser1", "pass", "pass"); + throw new RuntimeException( + " Certificate chain is not valid, test should not pass." + + " Test failed."); + } catch (KeyStoreException e) { + e.printStackTrace(); + out.println(" Certificate chain is not valid,exception is" + + " expected. Test passed."); + } + /* + * WriteP12PrivateKey:This test creates a p12 contains a self-signed + * cert and private key,expects no exception + */ + out.println("test WriteP12PrivateKey"); + jstest.test(null, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", "pass", + "pass"); + + /* + * WriteP12TwoEntry: This test creates a p12 keystore with different + * storepass and keypass, and contains two entries. + */ + out.println("test WriteP12TwoEntry"); + jstest.testTwoEntry(IN_KEYSTORE_ENDUSER, IN_KEYSTORE_CA, + "pkcs12testenduser1", "pass", "pass"); + /* + * WriteP12TwoPass: This test creates a p12 keystore with different + * storepass and keypass, and contains one entry with private key and a + * certificate + */ + out.println("test WriteP12TwoPass"); + jstest.test(null, IN_KEYSTORE_CA, "pkcs12testCA", "storepass", + "keypass"); + } + + private void test(Certificate certs[], String inKeyStorePath, + String userAlias, String outStorePass, String outKeyPass) + throws KeyStoreException, NoSuchProviderException, IOException, + CertificateException, UnrecoverableKeyException, + NoSuchAlgorithmException { + // init output key store + KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE"); + outputKeyStore.load(null, null); + try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE)) { + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need + // decode first. + byte[] input = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStorePath)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(input)); + // input key store + KeyStore inputKeyStore = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray()); + // add key/certificate to output key store + Key key = inputKeyStore + .getKey(userAlias, IN_KEY_PASS.toCharArray()); + out.println("Input Key Algorithm " + key.getAlgorithm()); + out.println("====Input Certs====="); + if (certs == null) { + certs = new Certificate[] { inputKeyStore + .getCertificate(userAlias) }; + } + for (Certificate cert : certs) { + out.println(((X509Certificate) cert).getSubjectDN()); + } + outputKeyStore.setKeyEntry(userAlias, key, + outKeyPass.toCharArray(), certs); + Certificate retCerts[] = outputKeyStore + .getCertificateChain(userAlias); + out.println("====Output Certs====="); + for (Certificate retCert : retCerts) { + out.println(((X509Certificate) retCert).getSubjectDN()); + } + out.println("====Output Key Algorithm====="); + Key outKey = outputKeyStore.getKey(userAlias, + outKeyPass.toCharArray()); + out.println(outKey.getAlgorithm()); + + if (!key.equals(outKey)) { + throw new RuntimeException("key don't match"); + } + if (!Arrays.equals(certs, retCerts)) { + throw new RuntimeException("certs don't match"); + } + // save output + outputKeyStore.store(fout, outStorePass.toCharArray()); + // test output + testKeyStore(outputKeyStore, outKeyPass.toCharArray()); + } + } + + private void testTwoEntry(String inKeyStoreOnePath, + String inKeyStoreTwoPath, String userAlias, String outStorePass, + String outKeyPass) throws KeyStoreException, + NoSuchProviderException, NoSuchAlgorithmException, + CertificateException, IOException, UnrecoverableKeyException { + // initial KeyStore + KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE"); + try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE);) { + outputKeyStore.load(null, null); + KeyStore inputKeyStoreOne, inputKeyStoreTwo; + inputKeyStoreOne = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need + // decode first. + byte[] inputBytes = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStoreOnePath)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(inputBytes)); + // input key store + inputKeyStoreOne.load(arrayIn, IN_STORE_PASS.toCharArray()); + + inputBytes = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStoreTwoPath)); + arrayIn = new ByteArrayInputStream(Base64.getMimeDecoder().decode( + inputBytes)); + inputKeyStoreTwo = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + inputKeyStoreTwo.load(arrayIn, IN_STORE_PASS.toCharArray()); + + // add key/certificate to output key store + out.println("====First Entry====="); + Key inputKey = inputKeyStoreOne.getKey(userAlias, + IN_KEY_PASS.toCharArray()); + Certificate cert = inputKeyStoreOne.getCertificate(userAlias); + Certificate certs[] = new Certificate[1]; + certs[0] = cert; + + out.println("====Input1 Key====="); + out.println(inputKey.getAlgorithm()); + out.println("====Input1 Certs====="); + out.println("Certificate :"); + out.println(((X509Certificate) cert).getSubjectDN()); + outputKeyStore.setKeyEntry("USER", inputKey, + outKeyPass.toCharArray(), certs); + out.println("====Second Entry====="); + String caAlias = "pkcs12testca"; + inputKey = inputKeyStoreTwo.getKey(caAlias, + IN_KEY_PASS.toCharArray()); + cert = inputKeyStoreTwo.getCertificate(caAlias); + certs[0] = cert; + out.println("====Input2 Key====="); + out.println(inputKey.getAlgorithm()); + out.println("====Input2 Certs====="); + out.println("Certificate :"); + out.println(((X509Certificate) cert).getSubjectDN()); + outputKeyStore.setKeyEntry("CA", inputKey, + outKeyPass.toCharArray(), certs); + // save output + outputKeyStore.store(fout, outStorePass.toCharArray()); + // test output + testKeyStore(outputKeyStore, outKeyPass.toCharArray()); + } + } + + private void testKeyStore(KeyStore inputKeyStore, char[] keypass) + throws KeyStoreException, UnrecoverableKeyException, + NoSuchAlgorithmException { + out.println("========== Key Store =========="); + out.println("getProvider : " + inputKeyStore.getProvider()); + out.println("getType : " + inputKeyStore.getType()); + out.println("getDefaultType : " + KeyStore.getDefaultType()); + + int idx = 0; + Enumeration e = inputKeyStore.aliases(); + String alias; + while (e.hasMoreElements()) { + alias = e.nextElement(); + if (!inputKeyStore.containsAlias(alias)) { + throw new RuntimeException("Alias not found"); + } + out.println("Alias " + idx + " : " + alias); + out.println("getCreationDate : " + + inputKeyStore.getCreationDate(alias)); + X509Certificate cert = (X509Certificate) inputKeyStore + .getCertificate(alias); + out.println("getCertificate : " + cert.getSubjectDN()); + String retAlias = inputKeyStore.getCertificateAlias(cert); + if (!retAlias.equals(alias)) { + throw new RuntimeException("Alias mismatch, actually " + + retAlias + ", expected " + alias); + } + out.println("getCertificateAlias : " + retAlias); + Certificate[] certs = inputKeyStore.getCertificateChain(alias); + int i = 0; + for (Certificate certification : certs) { + out.println("getCertificateChain " + i + + ((X509Certificate) certification).getSubjectDN()); + i++; + } + if (inputKeyStore.isCertificateEntry(alias)) { + throw new RuntimeException( + "inputKeystore should not be certEntry because this" + + " keystore only contain key pair entries."); + } + if (!inputKeyStore.isKeyEntry(alias)) { + throw new RuntimeException("Entry type unknown."); + } + idx++; + } + int size = inputKeyStore.size(); + if (idx != size) { + throw new RuntimeException("Size not match, actually " + idx + + ", expected " + size); + } + } + +} diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,38 @@ +/u3+7QAAAAIAAAABAAAAAQAMcGtjczEydGVzdGNhAAAA9w1mDAMAAAUCMIIE/jAOBgorBgEEASoC +EQEBBQAEggTqFhceJz85XyVsicsfonXYx+vvFXkb9Jmr11eh9n570ZdiFZ1hv4XRk/x/1C1spy5X +J2wv4lABGAOA5gV0aTKij+82NLoEz9zDW5fwAnrBKVjAq/NxdwEi9lvipiSVx1qglx/mQAHeEi4i +6vDoai3hVNQqVmd/TG2deyk/fQ9MZ7U2fmWcJDH4YbP39psQ+7rp9cDJ0P7GWoLXwbWs1vftbN0R +4fWitH1+6hBbIbVT9o0cM9ilAjpkNFr10pBEsfrikaE8IsN562soWfNxGwwrsjExEFeKlMrtNtWM +Wc4+YZ1ybVi/6krK/kFfOa+R3mtjBoD7zM4TSG9dptuvBLVgey8RXh3BQ8pU7uN5q+9Omqo1SsRN +wHYKjTrfWMozt+37ZlyCZ70Kb/2jJYWFuo9+wqXQU+MYnpZZB+cLt3PIFMakhIu1vpMpJCcoceaS +bjDWxCG8HHZjjFJPxAE3HEbCzaj4BevxQfxtp57llmtI2I0NJvua8JbFjf0U9MK6iRi4IpmBztpP +vxvaetT54wC+2c0QaDqANIn3Oc4tmvD4RGJfmFrEYEX6dQbCwYHAJF8sczqDb4xIYwrGmiMNeeha +4g9fcEa7Q+t1o1XLmNOp5e6I/TjUfXGvKlEyYeQ1FNLRqTtI5KvHQ1l71n1aQyEPvcff93NlF3jv +jWuqOqLzFT7sIZQxgjoum4i0DwLzOtuAWIDELNJ03MCciq5j0SjoLO2/ISctNTyGuYBmerjGCI9c +CLhGYnwLCOvvZN1yIqT79Se6qe/tBV5nEYUdXEt4ROJNabf1H4GmkXYeDQvtHrQ1IHM+Kg1UyEJz +fwdhJ68EU3gFenTtFgVJ+90YpemGtptgS6CvS3qC2H/H3XaKKQGpsXRCMSCRZcfMMOQEc6WLPsVY +rEhorQIAbbgHp4//H+RkNzG+5NN4pac5bo0kDTpeQkiOXGZZKyMHgagFvwLCN35rTi2HnHEXnYoi +jU1sGmUV+kRgRJ+N3Gx6D+uWNctkZMeTuVg+9ftIhEClGdtBSXWZu9lr/48cXkWJBubd4CWYrFMm +cTYezlQiTvmQgodrrwtcdo17J/L4PK74C72aIqPlWdEImGQs7I4n1mvceXoHvjYu5+tOxS0HH4sm +Y4iMr3hsqVAag2/LeLCG1gumpGiTdh9hk/aOcSWASv7rjq8JVpxWJe3JbrQ5k0U3e1nE2AdSXjEj +knBDpDFpGsnJaP2xxTdvQ+oV1pZ3m30xOeCTVV+0VBIw8eL0PDATSgqQ7FuWnYZ/FGaOrgnn14JM +HQicEfFN7TOa8q3/lbY5JTRtuG5umoWL2AWaaAW6G5GRTUNMOvBI5xTvR/kr3iNKTK2caKi0XTJ3 +WXd9jeuyLstpbtokG6xBbSiAb/SSL9yoh400DbKFTlVHKD8cijfuLKIM1TmL2ZksEh6JvF8GfdLl +FXZH7Ny8aJ63Ef947P9Y8+6WMzZDrkyoV+uInRq1TVXk6Ps6qiqI0j9fhMI8XMju61vjkeXprzBE +Pk2GbXo7MtHrBTobffkD3BszrFJai8n9vDrQgsaZYwWi4IxlKYefmWDaagiq/qDBZhKQCgyuJNN/ +5sQZDb6+J/MIgDk0M2bXEs6f2gT1rAyuH+rbnsnfUu9jRQupP4q0/ZCY2WOIaf8W34FnMdNzOUH8 +iE2T59UbMGQ0DLJeHwAAAAEABVguNTA5AAADGzCCAxcwggH/AgQ/PtJwMA0GCSqGSIb3DQEBBQUA +MFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FF +MRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTAeFw0wMzA4MTcwMDU1MTJaFw0xMzA4MTQwMDU1MTJa +MFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FF +MRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJO0ofiv8hrJiWnGZ435GX7lsRjSQj1tKuvXscKET/ngRzEMBtNMovWi0rGQKjaSUgg76YMkjgFJ +gXfn/FhYR6iX0VURFX795q2nQymQo4arbFCOyMEU2GMvXJRZHniuHR2sW7hTD6VLu8kH8Ek14Lzg +P1CeJCbhrWmAHUySOHn9ZlAEqOvnXmtFGQPxRwrlezus94a+VR5coSS9v6P/DObRgUwSEjgyUp5x +jQb7UCzR51mL7OO9FABNgbbghmIdVf9xwB9bUYq0tzAQXG9V5yJIol0d7Y2gUgfl4aAn7hvCrSJ1 +1xWgJ7yn2PZmBcOlSbfSWEKWNlQwu9vNfz289HUCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAc12f +Mx1q5wvPxPjf59gs4cYtfGEHNiz1gQy2E08aBRGs1pmC79ZPyU+zbWtartarr8VyeLldVx23fTRQ +CVisLRUBKX7+KOiO6llD6MZ3wPo8qil8b9u89ubc7fmOMThIarztNxtEIpoZIjbfTBey+vctlNP1 +O9/rhTRs3QBA4iPRIm7yAojp69U3kORnpCt2G5Oant5b4jGT5JEl3qUySPJtAIlwo4vnl4/e41S3 +h/kcXgXIQWPrhC66lK7FTlVoeyAQqgv1exalE5Jg9SBZc5JIp2raZeNrNTG4SSHdskJM2ngUXLLh +Ot2wxLbkVqfcpzDt0AOGLvObgUVhs0NQ4nYQH5SPMKBNY+nGGfmMLaFPAelF \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,79 @@ +/u3+7QAAAAIAAAADAAAAAgAMcGtjczEydGVzdGNhAAAA9w18bwQABVguNTA5AAADGzCCAxcwggH/ +AgQ/PtJwMA0GCSqGSIb3DQEBBQUAMFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEV +MBMGA1UECxMMU2VjdXJpdHkgU1FFMRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTAeFw0wMzA4MTcw +MDU1MTJaFw0xMzA4MTQwMDU1MTJaMFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEV +MBMGA1UECxMMU2VjdXJpdHkgU1FFMRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJO0ofiv8hrJiWnGZ435GX7lsRjSQj1tKuvXscKET/ngRzEM +BtNMovWi0rGQKjaSUgg76YMkjgFJgXfn/FhYR6iX0VURFX795q2nQymQo4arbFCOyMEU2GMvXJRZ +HniuHR2sW7hTD6VLu8kH8Ek14LzgP1CeJCbhrWmAHUySOHn9ZlAEqOvnXmtFGQPxRwrlezus94a+ +VR5coSS9v6P/DObRgUwSEjgyUp5xjQb7UCzR51mL7OO9FABNgbbghmIdVf9xwB9bUYq0tzAQXG9V +5yJIol0d7Y2gUgfl4aAn7hvCrSJ11xWgJ7yn2PZmBcOlSbfSWEKWNlQwu9vNfz289HUCAwEAATAN +BgkqhkiG9w0BAQUFAAOCAQEAc12fMx1q5wvPxPjf59gs4cYtfGEHNiz1gQy2E08aBRGs1pmC79ZP +yU+zbWtartarr8VyeLldVx23fTRQCVisLRUBKX7+KOiO6llD6MZ3wPo8qil8b9u89ubc7fmOMThI +arztNxtEIpoZIjbfTBey+vctlNP1O9/rhTRs3QBA4iPRIm7yAojp69U3kORnpCt2G5Oant5b4jGT +5JEl3qUySPJtAIlwo4vnl4/e41S3h/kcXgXIQWPrhC66lK7FTlVoeyAQqgv1exalE5Jg9SBZc5JI +p2raZeNrNTG4SSHdskJM2ngUXLLhOt2wxLbkVqfcpzDt0AOGLvObgUVhs0NQ4gAAAAIADnBrY3Mx +MnRlc3RsZWFkAAAA9w1+meMABVguNTA5AAACxDCCAsAwggGooAMCAQICBD8+0tYwDQYJKoZIhvcN +AQEEBQAwUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0 +eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3 +MDAwMFowUjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0 +eSBTUUUxGTAXBgNVBAMTEFBLQ1MxMiBUZXN0IExlYWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ +AoGBAM6vV9lEs/1ow4U/o1MmVqgeYeAN97UtdWKh+amL6o0143FCOoDqZqFzGnwxvUR0ZSHHL6ed +cS6ewKd1jK7+NdZVgbbarWYuXNfwxAtXBDP0pTwpNa9sxW5Cbu0Conl3jHK42RKOi3ARzMEIyKSP +rqfXK91Y7sqhv6JUJFJl1bktAgMBAAGjJDAiMA8GA1UdDwEB/wQFAwMHgAAwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAYW7opvfE1prb/b0pXURO0b0PBZUtE8mVTu5HEjbXwlBO +Ee+idRJTe+CqHOaUJ1LXbi3kCbNmqP5hHAmbBM1XMCN5kma0sz4XPLO8OYDkAOE1MFS0koyoAQmm +e0d/qid0HqjyeTurBc6bwWJIEmuDFqbSuNY25k/HMGUCVxQovFsRRSfqfexdT6Zty4JmJrYlD+DG +UMDgb6U2Vl1NFq6hV6c1kMdJoOEl9fX2ZuJy3CQHqwhFKYX/CC2oLaUDBBK09/44OpnwnU90Y9Oe +UFz3xeDokRXrzxeWtX2YKwnjwrpEUGXHe7PCuTgSGq8rjNDHRbZc8Yul1nlDaVRRR1EXMgAAAAEA +EnBrY3MxMnRlc3RlbmR1c2VyMQAAAPcNgTivAAACuTCCArUwDgYKKwYBBAEqAhEBAQUABIICoU6N +bD6qkNDM8KJFHCTHUevURAV8SUuzzBwsfYC0tEDMa2zGNUEvrmgyM3b5z7qR8XbTZvVBFJJLp3Jx +HmQpg0vLltDFFIPiVgRVcUEDPSmks1KP/bP/mE1uos31R6VyfNMGS3JnQblcSipcB893NrFFXNu2 +PUPjKCC9GrQZAmSM78BBTrwWD/Yd4rKcVh57DLKtUySoF29qXthusJjhSaqRZERaMV6egviE5+W8 +f8ppTYLx2gJmOyi9edJEdHxMcPzRvWgxlmUqUCDg0KVsosbxjjJKcmJ9b1KWuadKyAYkqxSDi8sx +2iwEQW3PQjLGBVHeQNntUF1wapp21sD1lVmDV3+61+fIphAUVRQXjmoYsEhrTc93IkDtQWgfJsgz +xjVVDbcy29VnMAK4f3tT/p5HeFO6yRQBE2B3IngSomRxbNh143VswNYqtZYy03UhOm8vbF2OfOJ/ +NzwC/F+19XgntnC0qv5j6VzwMGTt2NYPWXUqSzVIFswSunj70+ZsprCRX5IEFnpHDSL7OwDjEMFc +z6dpYQ9pwgyKh7JiLZxAr/9Nhb8QQDGrolzHoDt1QnC/DYvDGfTKu0ZjlXR4EQN4XFV+FAiykRfA +N1jIsTY7fCmLpLuW4paQnR1lPSGLeSvi63DOgN+lfVSJ5YjZm4yIRIS6lpvLVgcqodDqBRmPMP7x +fJ3osv1Wt4L/77BdJpZrUUygysRpzyUKlC6NwXr338HKPyAnfrkzIpHKnhTUaRVmfgAuzrXMFp8C +ejyYXJQwPPFAL5mIdUMkLDQKzESI0T3AD1LWVDM/0mGud9GhqiycI6AqC0j7MynRCvQG0LyRunFG +EQ2KipM//qPFKqwoVukxrLTunmGyeOe6UxodtK+qcn7SIXZ8jJM14a5rSDwAAAADAAVYLjUwOQAA +AjowggI2MIIBn6ADAgECAgQ/Pta3MA0GCSqGSIb3DQEBBAUAMFIxCzAJBgNVBAYTAlVTMREwDwYD +VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMRkwFwYDVQQDExBQS0NTMTIgVGVz +dCBMZWFkMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3MDAwMFowWDELMAkGA1UEBhMCVVMxETAP +BgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxHzAdBgNVBAMTFlBLQ1MxMiBU +ZXN0IEVuZCBVc2VyIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMgqiZJiiYPMf9Xrd4NA +Qbuh3QMtyedVnzWltaEOyzyAdXabykAN1Gp2KEGadJARoxbgPe5niwUTUu2RCWzqGN3tJ06wbljb +gvzXmOi31rYlwHvcfwfRUqKus5svkFl23sG0BI8Odi1bhKm375iMOgkXHIXQdyGRq/NdpVOV7FqT +AgMBAAGjEzARMA8GA1UdDwEB/wQFAwMHgAAwDQYJKoZIhvcNAQEEBQADgYEAgUDclcSZv0BefdEP +u34yfoOjJUMjLmOyfrE4pMlXbkjShukNTODDhBoAyYzRm+6w6ZnbBk1Lwy3JNSB0A3JqRvOflJ3F +tPJMsSpCwVtfxRULfx/HlkzoTEDlhIC+CZe51mk5ULQBNxyhlLckVTwLFJ9b5DcgLYwuH5BODeFQ +nlsABVguNTA5AAACxDCCAsAwggGooAMCAQICBD8+0tYwDQYJKoZIhvcNAQEEBQAwUDELMAkGA1UE +BhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMT +DlBLQ1MxMiBUZXN0IENBMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3MDAwMFowUjELMAkGA1UE +BhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxGTAXBgNVBAMT +EFBLQ1MxMiBUZXN0IExlYWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM6vV9lEs/1ow4U/ +o1MmVqgeYeAN97UtdWKh+amL6o0143FCOoDqZqFzGnwxvUR0ZSHHL6edcS6ewKd1jK7+NdZVgbba +rWYuXNfwxAtXBDP0pTwpNa9sxW5Cbu0Conl3jHK42RKOi3ARzMEIyKSPrqfXK91Y7sqhv6JUJFJl +1bktAgMBAAGjJDAiMA8GA1UdDwEB/wQFAwMHgAAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQQFAAOCAQEAYW7opvfE1prb/b0pXURO0b0PBZUtE8mVTu5HEjbXwlBOEe+idRJTe+CqHOaUJ1LX +bi3kCbNmqP5hHAmbBM1XMCN5kma0sz4XPLO8OYDkAOE1MFS0koyoAQmme0d/qid0HqjyeTurBc6b +wWJIEmuDFqbSuNY25k/HMGUCVxQovFsRRSfqfexdT6Zty4JmJrYlD+DGUMDgb6U2Vl1NFq6hV6c1 +kMdJoOEl9fX2ZuJy3CQHqwhFKYX/CC2oLaUDBBK09/44OpnwnU90Y9OeUFz3xeDokRXrzxeWtX2Y +KwnjwrpEUGXHe7PCuTgSGq8rjNDHRbZc8Yul1nlDaVRRR1EXMgAFWC41MDkAAAMbMIIDFzCCAf8C +BD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUw +EwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAw +NTUxMloXDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUw +EwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG +00yi9aLSsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7IwRTYYy9clFke +eK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4ef1mUASo6+dea0UZA/FHCuV7O6z3hr5V +HlyhJL2/o/8M5tGBTBISODJSnnGNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1Xn +IkiiXR3tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0dQIDAQABMA0G +CSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhxi18YQc2LPWBDLYTTxoFEazWmYLv1k/J +T7Nta1qu1quvxXJ4uV1XHbd9NFAJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhq +vO03G0QimhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Ybk5qe3lviMZPk +kSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUrsVOVWh7IBCqC/V7FqUTkmD1IFlzkkin +atpl42s1MbhJId2yQkzaeBRcsuE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di7p2dz0wNRNimbVP4 +VL+NWQOgtME= \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/Arrays/TimSortStackSize2.java --- a/jdk/test/java/util/Arrays/TimSortStackSize2.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/util/Arrays/TimSortStackSize2.java Sun Mar 29 09:21:15 2015 -0400 @@ -24,22 +24,63 @@ /* * @test * @bug 8072909 - * @run main/othervm -Xms385m TimSortStackSize2 67108864 + * @library /lib/testlibrary /../../test/lib + * @build jdk.testlibrary.* + * @build TimSortStackSize2 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TimSortStackSize2 * @summary Test TimSort stack size on big arrays - * big tests not for regular execution on all platforms: - * run main/othervm -Xmx8g TimSortStackSize2 1073741824 - * run main/othervm -Xmx16g TimSortStackSize2 2147483644 */ import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import java.util.function.Consumer; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; +import sun.hotspot.WhiteBox; + public class TimSortStackSize2 { public static void main(String[] args) { - int lengthOfTest = Integer.parseInt(args[0]); + if ( args == null || args.length == 0 ){ + startMeWithArgs(); + } else { + doTestOfTwoTimSorts(Integer.parseInt(args[0])); + } + } + + private static void startMeWithArgs(){ + /* + * big tests not for regular execution on all platforms: + * run main/othervm -Xmx8g TimSortStackSize2 1073741824 + * run main/othervm -Xmx16g TimSortStackSize2 2147483644 + */ + try { + Boolean compressedOops = WhiteBox.getWhiteBox() + .getBooleanVMFlag("UseCompressedOops"); + final String xmsValue = "-Xms" + + ((compressedOops == null || compressedOops) ? "385" : "770") + + "m"; + System.out.println( "compressedOops: " + compressedOops + + "; Test will be started with \"" + xmsValue + "\""); + ProcessBuilder processBuilder = ProcessTools + .createJavaProcessBuilder(Utils.addTestJavaOpts(xmsValue, + "TimSortStackSize2", "67108864" + ) + ); + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); + System.out.println(output.getOutput()); + output.shouldHaveExitValue(0); + } catch( Exception e ){ + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + private static void doTestOfTwoTimSorts(final int lengthOfTest){ boolean passed = doTest("TimSort", lengthOfTest, (Integer [] a) -> Arrays.sort(a)); passed = doTest("ComparableTimSort", lengthOfTest, (Integer [] a) -> diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/Properties/Basic.java --- a/jdk/test/java/util/Properties/Basic.java Wed Mar 25 15:22:45 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.util.Properties; - -/* - * @test - * @bug 8073214 - * @summary Basic tests of Properties methods. - */ -public class Basic -{ - public static void main(String[] args) throws Exception - { - int failures = 0; - - Properties props = new Properties(); - - try { - props.store((OutputStream)null, "comments"); - failures++; - } catch (NullPointerException e) { - // do nothing - } - - try { - props.store((Writer)null, "comments"); - failures++; - } catch (NullPointerException e) { - // do nothing - } - - try { - props.load((InputStream)null); - failures++; - } catch (NullPointerException e) { - // do nothing - } - - try { - props.load((Reader)null); - failures++; - } catch (NullPointerException e) { - // do nothing - } - - if (failures != 0) { - throw new RuntimeException("Basic failed with " - + failures + " errors!"); - } - } -} diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/Properties/LoadAndStoreNPE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Properties/LoadAndStoreNPE.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Properties; + +/* + * @test + * @bug 8073214 8075362 + * @summary Tests to verify that load() and store() throw NPEs as advertised. + */ +public class LoadAndStoreNPE +{ + public static void main(String[] args) throws Exception + { + int failures = 0; + + Properties props = new Properties(); + + try { + props.store((OutputStream)null, "comments"); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + try { + props.store((Writer)null, "comments"); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + try { + props.load((InputStream)null); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + try { + props.load((Reader)null); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + if (failures != 0) { + throw new RuntimeException("LoadAndStoreNPE failed with " + + failures + " errors!"); + } + } +} diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java --- a/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -251,7 +251,7 @@ final int lastLimitIndex = l; return s -> { - if (lastLimitIndex == -1) + if (lastLimitIndex == -1 && fs.size() > 0) s = fi.apply(s); for (int i = 0; i < fs.size(); i++) { s = fs.get(i).apply(s); diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -24,11 +24,12 @@ /** * @test * @summary Tests counting of streams - * @bug 8031187 8067969 + * @bug 8031187 8067969 8075307 */ package org.openjdk.tests.java.util.stream; +import java.util.HashSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.DoubleStream; import java.util.stream.DoubleStreamTestDataProvider; @@ -59,6 +60,19 @@ terminal(s -> s.filter(e -> true), Stream::count). expectedResult(expectedCount). exercise(); + + // Test with stateful distinct op that is a barrier or lazy + // depending if source is not already distinct and encounter order is + // preserved or not + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(Stream::distinct, Stream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), Stream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) @@ -74,6 +88,16 @@ terminal(s -> s.filter(e -> true), IntStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(IntStream::distinct, IntStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), IntStream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) @@ -89,6 +113,16 @@ terminal(s -> s.filter(e -> true), LongStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(LongStream::distinct, LongStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), LongStream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) @@ -104,6 +138,16 @@ terminal(s -> s.filter(e -> true), DoubleStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(DoubleStream::distinct, DoubleStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), DoubleStream::count). + expectedResult(expectedCount). + exercise(); } public void testNoEvaluationForSizedStream() { @@ -111,24 +155,36 @@ AtomicInteger ai = new AtomicInteger(); Stream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + Stream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); IntStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + IntStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); LongStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + LongStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); DoubleStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + DoubleStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } } } diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,7 +128,7 @@ @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) public void testDistinctDistinct(String name, TestData.OfRef data) { Collection result = withData(data) - .stream(s -> s.distinct().distinct(), new CollectorOps.TestParallelSizedOp<>()) + .stream(s -> s.distinct().distinct()) .exercise(); assertUnique(result); } diff -r f07d88b6243c -r cdecfa325d0c jdk/test/java/util/zip/EntryCount64k.java --- a/jdk/test/java/util/zip/EntryCount64k.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/java/util/zip/EntryCount64k.java Sun Mar 29 09:21:15 2015 -0400 @@ -24,31 +24,64 @@ /** * @test * @summary Test java.util.zip behavior with ~64k entries + * @library /lib/testlibrary * @run main/othervm EntryCount64k * @run main/othervm -Djdk.util.zip.inhibitZip64=true EntryCount64k * @run main/othervm -Djdk.util.zip.inhibitZip64=false EntryCount64k */ import java.io.*; +import java.nio.file.Paths; import java.util.*; import java.util.zip.*; -public class EntryCount64k { +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; - public static void main(String[] args) throws Exception { - for (int i = (1 << 16) - 2; i < (1 << 16) + 2; i++) +public class EntryCount64k { + public static class Main { + public static void main(String[] args) { + System.out.println("Main"); + } + } + + static final String mainClass = "EntryCount64k$Main"; + + public static void main(String[] args) throws Throwable { + for (int i = (1 << 16) - 3; i < (1 << 16) + 2; i++) test(i); } - static void test(int entryCount) throws Exception { + static void test(int entryCount) throws Throwable { File zipFile = new File("EntryCount64k-tmp.zip"); zipFile.delete(); - try (ZipOutputStream zos = - new ZipOutputStream( - new BufferedOutputStream( - new FileOutputStream(zipFile)))) { - for (int i = 0; i < entryCount; i++) { + try (FileOutputStream fos = new FileOutputStream(zipFile); + BufferedOutputStream bos = new BufferedOutputStream(fos); + ZipOutputStream zos = new ZipOutputStream(bos)) { + + // Add 2 special entries, manifest and main class, + // to allow the zip file to be used with "java -jar" + ZipEntry man = new ZipEntry("META-INF/MANIFEST.MF"); + zos.putNextEntry(man); + zos.write("Manifest-Version: 1.0\n".getBytes("US-ASCII")); + zos.write(("Main-Class: " + mainClass + "\n").getBytes("US-ASCII")); + zos.closeEntry(); + + String mainName = mainClass + ".class"; + ZipEntry mainEntry = new ZipEntry(mainName); + String testClasses = System.getProperty("test.classes"); + File mainFile = new File(testClasses, mainName); + zos.putNextEntry(mainEntry); + try (FileInputStream fis = new FileInputStream(mainFile)) { + byte[] buf = new byte[4096]; + int n; + while ((n = fis.read(buf)) > 0) + zos.write(buf, 0, n); + } + zos.closeEntry(); + + for (int i = 2; i < entryCount; i++) { ZipEntry e = new ZipEntry(Integer.toString(i)); zos.putNextEntry(e); zos.closeEntry(); @@ -86,16 +119,19 @@ return false; } - static void checkCanRead(File zipFile, int entryCount) throws Exception { + static void checkCanRead(File zipFile, int entryCount) throws Throwable { // Check ZipInputStream API try (ZipInputStream zis = new ZipInputStream( new BufferedInputStream( new FileInputStream(zipFile)))) { - for (int i = 0; i < entryCount; i++) { + // skip over first two entries + for (int i = 0; i < 2; i++) + zis.getNextEntry(); + for (int i = 2; i < entryCount; i++) { ZipEntry e = zis.getNextEntry(); if (Integer.parseInt(e.getName()) != i) - throw new AssertionError(); + throw new AssertionError(e.getName()); } if (zis.getNextEntry() != null) throw new AssertionError(); @@ -104,7 +140,10 @@ // Check ZipFile API try (ZipFile zf = new ZipFile(zipFile)) { Enumeration en = zf.entries(); - for (int i = 0; i < entryCount; i++) { + // skip over first two entries + for (int i = 0; i < 2; i++) + en.nextElement(); + for (int i = 2; i < entryCount; i++) { ZipEntry e = en.nextElement(); if (Integer.parseInt(e.getName()) != i) throw new AssertionError(); @@ -115,5 +154,15 @@ || (zf.getEntry(Integer.toString(entryCount)) != null)) throw new AssertionError(); } + + // Check java -jar + String javaHome = System.getProperty("java.home"); + String java = Paths.get(javaHome, "bin", "java").toString(); + String[] cmd = { java, "-jar", zipFile.getName() }; + ProcessBuilder pb = new ProcessBuilder(cmd); + OutputAnalyzer a = ProcessTools.executeProcess(pb); + a.shouldHaveExitValue(0); + a.stdoutShouldMatch("\\AMain\n\\Z"); + a.stderrShouldMatch("\\A\\Z"); } } diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java --- a/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,7 +80,7 @@ } try { - urlc.getServerCertificateChain(); + urlc.getServerCertificates(); } catch (IllegalStateException e) { System.out.print("Caught proper exception: "); System.out.println(e.getMessage()); diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/net/ssl/TLS/TestJSSE.java --- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java Sun Mar 29 09:21:15 2015 -0400 @@ -70,6 +70,7 @@ * -DCLIENT_PROTOCOL=DEFAULT -Djdk.tls.client.protocols=TLSv1.2 * -DCIPHER=SSL_RSA_WITH_RC4_128_MD5 * TestJSSE javax.net.ssl.SSLHandshakeException + * @key intermittent * */ diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/security/auth/Subject/doAs/NestedActions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/Subject/doAs/NestedActions.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; +import jdk.testlibrary.ProcessTools; + +/** + * @test + * @bug 8048147 + * @summary Check if proper AccessControlException is thrown + * in case of nested Subject.doAs() invocations + * when one of protection domains doesn't have permissions + * + * @library /lib/testlibrary + * + * @run main NestedActions jar NestedActionsACE.jar + * NestedActionsACE.class Utils.class + * @run main NestedActions jar NestedActionsPAE.jar + * NestedActionsPAE.class Utils.class + * @run main NestedActions jar NestedActionsOnePrincipal.jar + * NestedActionsOnePrincipal.class Utils.class + * @run main NestedActions jar NestedActionsTwoPrincipals.jar + * NestedActionsTwoPrincipals.class Utils.class + * @run main NestedActions jar WriteToFileAction.jar + * WriteToFileAction.class + * @run main NestedActions jar WriteToFileNegativeAction.jar + * WriteToFileNegativeAction.class + * @run main NestedActions jar WriteToFileExceptionAction.jar + * WriteToFileExceptionAction.class + * @run main NestedActions jar ReadFromFileAction.jar + * ReadFromFileAction.class + * @run main NestedActions jar ReadFromFileNegativeAction.jar + * ReadFromFileNegativeAction.class + * @run main NestedActions jar ReadFromFileExceptionAction.jar + * ReadFromFileExceptionAction.class + * @run main NestedActions jar ReadPropertyAction.jar + * ReadPropertyAction.class + * @run main NestedActions jar ReadPropertyNegativeAction.jar + * ReadPropertyNegativeAction.class + * @run main NestedActions jar ReadPropertyExceptionAction.jar + * ReadPropertyExceptionAction.class ReadPropertyException.class + * + * @run main NestedActions NestedActionsACE policy.expect.ace + * NestedActionsACE.jar WriteToFileNegativeAction.jar + * ReadFromFileNegativeAction.jar ReadPropertyNegativeAction.jar + * @run main NestedActions NestedActionsPAE policy.expect.pae + * NestedActionsPAE.jar WriteToFileExceptionAction.jar + * ReadFromFileExceptionAction.jar ReadPropertyExceptionAction.jar + * @run main NestedActions NestedActionsOnePrincipal policy.one.principal + * NestedActionsOnePrincipal.jar WriteToFileAction.jar + * ReadFromFileAction.jar ReadPropertyAction.jar + * @run main NestedActions NestedActionsTwoPrincipals policy.two.principals + * NestedActionsTwoPrincipals.jar WriteToFileAction.jar + * ReadFromFileAction.jar ReadPropertyAction.jar + */ +public class NestedActions { + + static final String file = "NestedActions.tmp"; + static final String PS = System.getProperty("path.separator"); + static final String FS = System.getProperty("file.separator"); + static final String TEST_CLASSES = System.getProperty("test.classes"); + static final String TEST_SOURCES = System.getProperty("test.src"); + static final String JAVA_OPTS = System.getProperty("test.java.opts"); + static final String JAVA = System.getProperty("java.home") + + FS + "bin" + FS + "java"; + + public static void main(String[] args) throws IOException { + if (args.length > 0) { + if ("jar".equals(args[0]) && args.length > 2) { + createJar(args[1], + Arrays.copyOfRange(args, 2, args.length)); + } else { + runJava(args); + } + } else { + throw new RuntimeException("Wrong parameters"); + } + } + + static void createJar(String dest, String... files) throws IOException { + System.out.println("Create " + dest + " with the following content:"); + try (JarOutputStream jos = new JarOutputStream( + new FileOutputStream(dest), new Manifest())) { + for (String file : files) { + System.out.println(" " + file); + jos.putNextEntry(new JarEntry(file)); + try (FileInputStream fis = new FileInputStream( + TEST_CLASSES + FS + file)) { + fis.transferTo(jos); + } + } + } + } + + static void runJava(String[] args) { + if (args == null || args.length < 3) { + throw new IllegalArgumentException("wrong parameters"); + } + + List cmds = new ArrayList<>(); + cmds.add(JAVA); + StringBuilder sb = new StringBuilder(); + cmds.add("-classpath"); + for (int i=2; i + * ReadFromFileAction (CN=Duke principal) -> + * ReadPropertyAction (CN=Duke principal) + * + * The test expects PrivilegedActionException + * that caused by AccessControlEception. + */ +class NestedActionsPAE { + + public static void main(String args[]) { + Subject subject = new Subject(); + subject.getPrincipals().add(new X500Principal("CN=Duke")); + try { + WriteToFileExceptionAction writeToFile = + new WriteToFileExceptionAction(NestedActions.file); + Subject.doAs(subject, writeToFile); + throw new RuntimeException( + "Test failed: no PrivilegedActionException thrown"); + } catch (PrivilegedActionException pae) { + System.out.println( + "PrivilegedActionException thrown as expected: " + + pae); + + // check if AccessControlException caused PrivilegedActionException + Throwable exception = pae.getException(); + do { + if (!(exception instanceof PrivilegedActionException)) { + break; + } + exception = ((PrivilegedActionException) exception). + getException(); + } while (true); + + if (!(exception instanceof ReadPropertyException)) { + throw new RuntimeException( + "Test failed: PrivilegedActionException " + + "was not caused by ReadPropertyException"); + } + + exception = exception.getCause(); + if (!(exception instanceof AccessControlException)) { + throw new RuntimeException( + "Test failed: PrivilegedActionException " + + "was not caused by ReadPropertyException"); + } + + System.out.println( + "Test passed: PrivilegedActionException " + + "was caused by AccessControlException"); + } + } +} + +/** + * Test for nested Subject.doAs() invocation: + * + * WriteToFileAction (CN=Duke principal) -> + * ReadFromFileAction (CN=Duke principal) -> + * ReadPropertyAction (CN=Duke principal) + */ +class NestedActionsOnePrincipal { + + public static void main(String args[]) { + Subject subject = new Subject(); + subject.getPrincipals().add(new X500Principal("CN=Duke")); + WriteToFileAction writeToFile = + new WriteToFileAction(NestedActions.file); + Subject.doAs(subject, writeToFile); + } +} + +/** + * Test for nested Subject.doAs() invocation: + * + * WriteToFileAction (CN=Duke principal) -> + * ReadFromFileAction (CN=Duke principal) -> + * ReadPropertyAction (CN=Java principal) + */ +class NestedActionsTwoPrincipals { + + public static void main(String args[]) { + Subject subject = new Subject(); + subject.getPrincipals().add(new X500Principal("CN=Duke")); + Subject anotherSubject = new Subject(); + anotherSubject.getPrincipals().add(new X500Principal("CN=Java")); + ReadFromFileAction readFromFile + = new ReadFromFileAction(NestedActions.file, anotherSubject); + WriteToFileAction writeToFile + = new WriteToFileAction(NestedActions.file, readFromFile); + Subject.doAs(subject, writeToFile); + } +} + +/** + * Helper class. + */ +class Utils { + + static void readFile(String filename) { + System.out.println("ReadFromFileAction: try to read " + filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + try (FileInputStream fis = new FileInputStream(filename)) { + // do nothing + } catch (IOException e) { + throw new RuntimeException("Unexpected IOException", e); + } + } + + static void writeFile(String filename) { + System.out.println("WriteToFileAction: try to write to " + filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + try (BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(filename))) { + bos.write(0); + bos.flush(); + } catch (IOException e) { + throw new RuntimeException("Unexpected IOException", e); + } + } + +} + +class WriteToFileAction implements PrivilegedAction { + + private final String filename; + private final PrivilegedAction nextAction; + + WriteToFileAction(String filename, PrivilegedAction nextAction) { + this.filename = filename; + this.nextAction = nextAction; + } + + WriteToFileAction(String filename) { + this(filename, new ReadFromFileAction(filename)); + } + + @Override + public Object run() { + Utils.writeFile(filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + return Subject.doAs(subject, nextAction); + } + +} + +class ReadFromFileAction implements PrivilegedAction { + + private final String filename; + private final Subject anotherSubject; + + ReadFromFileAction(String filename) { + this(filename, null); + } + + ReadFromFileAction(String filename, Subject anotherSubject) { + this.filename = filename; + this.anotherSubject = anotherSubject; + } + + @Override + public Object run() { + Utils.readFile(filename); + + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + ReadPropertyAction readProperty = new ReadPropertyAction(); + if (anotherSubject != null) { + return Subject.doAs(anotherSubject, readProperty); + } else { + return Subject.doAs(subject, readProperty); + } + } + +} + +class ReadPropertyAction implements PrivilegedAction { + + @Override + public java.lang.Object run() { + System.out.println("ReadPropertyAction: " + + "try to read 'java.class.path' property"); + + AccessControlContext acc = AccessController.getContext(); + Subject s = Subject.getSubject(acc); + System.out.println("principals = " + s.getPrincipals()); + System.out.println("java.class.path = " + + System.getProperty("java.class.path")); + + return null; + } + +} + +class WriteToFileNegativeAction implements PrivilegedAction { + + private final String filename; + + public WriteToFileNegativeAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() { + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + + try { + Utils.writeFile(filename); + new File(filename).delete(); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + } + + ReadFromFileNegativeAction readFromFile + = new ReadFromFileNegativeAction(filename); + return Subject.doAs(subject, readFromFile); + } + +} + +class ReadFromFileNegativeAction implements PrivilegedAction { + + private final String filename; + + public ReadFromFileNegativeAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() { + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + System.out.println("principals = " + subject.getPrincipals()); + + try { + Utils.readFile(filename); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + } + + ReadPropertyNegativeAction readProperty = + new ReadPropertyNegativeAction(); + return Subject.doAs(subject, readProperty); + } + +} + +class ReadPropertyNegativeAction implements PrivilegedAction { + + @Override + public java.lang.Object run() { + System.out.println("Try to read 'java.class.path' property"); + + AccessControlContext acc = AccessController.getContext(); + Subject s = Subject.getSubject(acc); + System.out.println("principals = " + s.getPrincipals()); + + try { + System.out.println("java.class.path = " + + System.getProperty("java.class.path")); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + } + + return null; + } + +} + +class WriteToFileExceptionAction implements PrivilegedExceptionAction { + + private final String filename; + + WriteToFileExceptionAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() throws Exception { + Utils.writeFile(filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + ReadFromFileExceptionAction readFromFile = + new ReadFromFileExceptionAction(filename); + return Subject.doAs(subject, readFromFile); + } + +} + +class ReadFromFileExceptionAction implements PrivilegedExceptionAction { + + private final String filename; + + ReadFromFileExceptionAction(String filename) { + this.filename = filename; + } + + @Override + public Object run() throws Exception { + Utils.readFile(filename); + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + ReadPropertyExceptionAction readProperty = + new ReadPropertyExceptionAction(); + return Subject.doAs(subject, readProperty); + } + +} + +class ReadPropertyExceptionAction implements PrivilegedExceptionAction { + + @Override + public java.lang.Object run() throws Exception { + System.out.println("Try to read 'java.class.path' property"); + + AccessControlContext acc = AccessController.getContext(); + Subject s = Subject.getSubject(acc); + System.out.println("principals = " + s.getPrincipals()); + + try { + System.out.println("java.class.path = " + + System.getProperty("java.class.path")); + throw new RuntimeException( + "Test failed: no AccessControlException thrown"); + } catch (AccessControlException ace) { + System.out.println( + "AccessControlException thrown as expected: " + + ace.getMessage()); + throw new ReadPropertyException(ace); + } + } + +} + +class ReadPropertyException extends Exception { + + ReadPropertyException(Throwable cause) { + super(cause); + } +} diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,27 @@ +// this code has limited permissions that should cause ACE +grant codeBase "file:NestedActionsACE.jar" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "test.java.opts", "read"; + permission java.util.PropertyPermission "java.home", "read"; +}; + +grant codeBase "file:WriteToFileNegativeAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +grant codeBase "file:ReadFromFileNegativeAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +grant codeBase "file:ReadPropertyNegativeAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,19 @@ +grant codeBase "file:NestedActionsPAE.jar" { + permission java.security.AllPermission; +}; + +grant codeBase "file:WriteToFileExceptionAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +grant codeBase "file:ReadFromFileExceptionAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission java.security.AllPermission; +}; + +// this code has limited permissions that should cause ACE +grant codeBase "file:ReadPropertyExceptionAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; +}; diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/security/auth/Subject/doAs/policy.one.principal --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,36 @@ +grant codeBase "file:NestedActionsOnePrincipal.jar" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "test.java.opts", "read"; + permission java.util.PropertyPermission "java.home", "read"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write"; +}; + +grant codeBase "file:WriteToFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write"; +}; + +grant codeBase "file:ReadFromFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read"; +}; + +grant codeBase "file:ReadPropertyAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; +}; \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c jdk/test/javax/security/auth/Subject/doAs/policy.two.principals --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,37 @@ +grant codeBase "file:NestedActionsTwoPrincipals.jar" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "test.java.opts", "read"; + permission java.util.PropertyPermission "java.home", "read"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write,delete"; +}; + +grant codeBase "file:WriteToFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read,write"; +}; + +grant codeBase "file:ReadFromFileAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Duke"{ + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; + permission java.io.FilePermission "NestedActions.tmp", "read"; +}; + +grant codeBase "file:ReadPropertyAction.jar" + Principal javax.security.auth.x500.X500Principal "cn=Java" { + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "doAs"; + permission java.util.PropertyPermission "java.class.path", "read"; +}; \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java --- a/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java Sun Mar 29 09:21:15 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,8 @@ import java.io.*; import java.net.*; +import java.security.cert.Certificate; import javax.net.ssl.*; -import javax.security.cert.*; import com.sun.net.ssl.HostnameVerifier; import com.sun.net.ssl.HttpsURLConnection; @@ -240,8 +240,8 @@ System.out.println("Cipher Suite: " + ((HttpsURLConnection)urlc).getCipherSuite()); - X509Certificate[] certs = - ((HttpsURLConnection)urlc).getServerCertificateChain(); + Certificate[] certs = + ((HttpsURLConnection)urlc).getServerCertificates(); for (int i = 0; i < certs.length; i++) { System.out.println(certs[0]); } diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/security/mscapi/ShortRSAKey1024.sh --- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Sun Mar 29 09:21:15 2015 -0400 @@ -30,6 +30,7 @@ # @run shell ShortRSAKey1024.sh 1024 # @run shell ShortRSAKey1024.sh 768 # @run shell ShortRSAKey1024.sh 512 +# @key intermittent # set a few environment variables so that the shell-script can run stand-alone # in the source directory diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh --- a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Sun Mar 29 09:21:15 2015 -0400 @@ -28,6 +28,7 @@ # @bug 6578658 # @run shell SignUsingNONEwithRSA.sh # @summary Sign using the NONEwithRSA signature algorithm from SunMSCAPI +# @key intermittent # set a few environment variables so that the shell-script can run stand-alone # in the source directory diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/security/provider/X509Factory/BadPem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/provider/X509Factory/BadPem.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8074935 + * @summary jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did + */ + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.Base64; + +import sun.security.provider.X509Factory; +import java.security.cert.CertificateFactory; +import java.io.ByteArrayInputStream; + +public class BadPem { + + public static void main(String[] args) throws Exception { + String ks = System.getProperty("test.src", ".") + + "/../../../../javax/net/ssl/etc/keystore"; + String pass = "passphrase"; + String alias = "dummy"; + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new FileInputStream(ks), pass.toCharArray()); + byte[] cert = keyStore.getCertificate(alias).getEncoded(); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream pout = new PrintStream(bout); + byte[] CRLF = new byte[] {'\r', '\n'}; + pout.println(X509Factory.BEGIN_CERT); + for (int i=0; i i + 48) ? 48 : (cert.length - i); + pout.println("!" + Base64.getEncoder() + .encodeToString(Arrays.copyOfRange(cert, i, i + blockLen))); + } + pout.println(X509Factory.END_CERT); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + try { + cf.generateCertificate(new ByteArrayInputStream(bout.toByteArray())); + throw new Exception("Should fail"); + } catch (CertificateException e) { + // Good + } + } +} + diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/security/tools/keytool/KeyToolTest.java --- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -56,6 +56,8 @@ * NSS PKCS11 config file are changed, DSA not supported now. */ +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; import sun.security.x509.*; import java.io.*; @@ -1222,6 +1224,24 @@ remove("mykey.cert"); } + // 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness + static void checkPem(String file) throws Exception { + boolean maybeLast = false; + for (String s: Files.readAllLines(Paths.get(file))) { + if (s.isEmpty()) continue; + if (s.startsWith("---")) continue; + if (maybeLast) { + throw new Exception("Last line already seen"); + } + if (s.length() > 64) { + throw new Exception(s); + } + if (s.length() < 64) { + maybeLast = true; + } + } + } + void v3extTest(String keyAlg) throws Exception { KeyStore ks; remove("x.jks"); @@ -1588,12 +1608,14 @@ "-rfc -file test.req"); // printcertreq testOK("", "-printcertreq -file test.req"); + checkPem("test.req"); // issue: deny KU, change criticality of 1.2.3 and 1.2.4, // change content of BC, add 2.3.4 testOK("", simple+"-gencert -alias ca -infile test.req -ext " + "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " + "-ext BC=2 -ext 2.3.4=01020304 " + "-debug -rfc -outfile test.cert"); + checkPem("test.cert"); testOK("", simple+"-importcert -file test.cert -alias a"); ks = loadStore("x.jks", "changeit", "JKS"); X509CertImpl a = (X509CertImpl)ks.getCertificate("a"); diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/text/resources/LocaleData --- a/jdk/test/sun/text/resources/LocaleData Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/text/resources/LocaleData Sun Mar 29 09:21:15 2015 -0400 @@ -8279,3 +8279,6 @@ FormatData/fi/DatePatterns/1=d. MMMM yyyy FormatData/fi/DatePatterns/2=d.M.yyyy FormatData/fi/DatePatterns/3=d.M.yyyy + +# bug #8075173 +FormatData/de/standalone.MonthAbbreviations/2=M\u00e4r diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/text/resources/LocaleDataTest.java --- a/jdk/test/sun/text/resources/LocaleDataTest.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/text/resources/LocaleDataTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -36,7 +36,7 @@ * 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495 * 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509 * 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 8017142 - * 8037343 8055222 8042126 8074791 + * 8037343 8055222 8042126 8074791 8075173 * @summary Verify locale data * */ diff -r f07d88b6243c -r cdecfa325d0c jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java --- a/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java Wed Mar 25 15:22:45 2015 +0000 +++ b/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java Sun Mar 29 09:21:15 2015 -0400 @@ -417,7 +417,9 @@ setLastModified(theLockFileName, epoch()); Thread.sleep(spinDelay); } - + } catch (NoSuchFileException ex) { + // Lock deleted while we are setting last modified time. + // Ignore error and lets the app exits } catch (Exception ex) { System.err.println("LingeredApp ERROR: " + ex); // Leave exit_code = 1 to Java launcher diff -r f07d88b6243c -r cdecfa325d0c langtools/.hgtags --- a/langtools/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -297,3 +297,4 @@ ee20efe0255d7ac6e06e88e06f7c72f6c6da7bf9 jdk9-b52 99ff00581f3633c1787bec21f2a8f3a2ffe57665 jdk9-b53 ed34864f3b43a7df394fce6c3f0bc86b70a5d686 jdk9-b54 +32a2e724988499e6f68611a65168c5f2fde0f6b9 jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Sun Mar 29 09:21:15 2015 -0400 @@ -31,10 +31,12 @@ import java.util.EnumSet; import java.util.Map; import java.util.Set; +import java.util.function.Function; import javax.lang.model.type.*; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Types.MapVisitor; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.DefinedBy.Api; import static com.sun.tools.javac.code.BoundKind.*; @@ -218,33 +220,81 @@ /** An abstract class for mappings from types to types */ - public static abstract class Mapping { - private String name; - public Mapping(String name) { - this.name = name; + public static abstract class TypeMapping extends Types.MapVisitor implements Function { + + @Override + public Type apply(Type type) { + return visit(type); + } + + List visit(List ts, S s) { + return ts.map(t -> visit(t, s)); + } + + @Override + public Type visitClassType(ClassType t, S s) { + Type outer = t.getEnclosingType(); + Type outer1 = visit(outer, s); + List typarams = t.getTypeArguments(); + List typarams1 = visit(typarams, s); + if (outer1 == outer && typarams1 == typarams) return t; + else return new ClassType(outer1, typarams1, t.tsym, t.metadata); + } + + @Override + public Type visitWildcardType(WildcardType wt, S s) { + Type t = wt.type; + if (t != null) + t = visit(t, s); + if (t == wt.type) + return wt; + else + return new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.metadata); } - public abstract Type apply(Type t); - public String toString() { - return name; + + @Override + public Type visitArrayType(ArrayType t, S s) { + Type elemtype = t.elemtype; + Type elemtype1 = visit(elemtype, s); + if (elemtype1 == elemtype) return t; + else return new ArrayType(elemtype1, t.tsym, t.metadata); + } + + @Override + public Type visitMethodType(MethodType t, S s) { + List argtypes = t.argtypes; + Type restype = t.restype; + List thrown = t.thrown; + List argtypes1 = visit(argtypes, s); + Type restype1 = visit(restype, s); + List thrown1 = visit(thrown, s); + if (argtypes1 == argtypes && + restype1 == restype && + thrown1 == thrown) return t; + else return new MethodType(argtypes1, restype1, thrown1, t.tsym); + } + + @Override + public Type visitCapturedType(CapturedType t, S s) { + return visitTypeVar(t, s); + } + + @Override + public Type visitForAll(ForAll t, S s) { + return visit(t.qtype, s); } } /** map a type function over all immediate descendants of this type */ - public Type map(Mapping f) { - return this; + public Type map(TypeMapping mapping, Z arg) { + return mapping.visit(this, arg); } - /** map a type function over a list of types + /** map a type function over all immediate descendants of this type (no arg version) */ - public static List map(List ts, Mapping f) { - if (ts.nonEmpty()) { - List tail1 = map(ts.tail, f); - Type t = f.apply(ts.head); - if (tail1 != ts.tail || t != ts.head) - return tail1.prepend(t); - } - return ts; + public Type map(TypeMapping mapping) { + return mapping.visit(this, null); } /** Define a constant type, of the same kind as this type @@ -775,17 +825,6 @@ return s.toString(); } - public Type map(Mapping f) { - //- System.err.println(" (" + this + ").map(" + f + ")");//DEBUG - Type t = type; - if (t != null) - t = f.apply(t); - if (t == type) - return this; - else - return new WildcardType(t, kind, tsym, bound, metadata); - } - @DefinedBy(Api.LANGUAGE_MODEL) public Type getExtendsBound() { if (kind == EXTENDS) @@ -1009,15 +1048,6 @@ allparams().isEmpty(); } - public Type map(Mapping f) { - Type outer = getEnclosingType(); - Type outer1 = f.apply(outer); - List typarams = getTypeArguments(); - List typarams1 = map(typarams, f); - if (outer1 == outer && typarams1 == typarams) return this; - else return new ClassType(outer1, typarams1, tsym, metadata); - } - public boolean contains(Type elem) { return elem == this @@ -1248,12 +1278,6 @@ }; } - public Type map(Mapping f) { - Type elemtype1 = f.apply(elemtype); - if (elemtype1 == elemtype) return this; - else return new ArrayType(elemtype1, tsym, metadata); - } - public boolean contains(Type elem) { return elem == this || elemtype.contains(elem); } @@ -1345,16 +1369,6 @@ restype != null && restype.isErroneous(); } - public Type map(Mapping f) { - List argtypes1 = map(argtypes, f); - Type restype1 = f.apply(restype); - List thrown1 = map(thrown, f); - if (argtypes1 == argtypes && - restype1 == restype && - thrown1 == thrown) return this; - else return new MethodType(argtypes1, restype1, thrown1, tsym); - } - public boolean contains(Type elem) { return elem == this || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem); } @@ -1647,10 +1661,6 @@ return qtype.isErroneous(); } - public Type map(Mapping f) { - return f.apply(qtype); - } - public boolean contains(Type elem) { return qtype.contains(elem); } @@ -1820,7 +1830,7 @@ } protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) { - Type bound2 = toTypeVarMap.apply(bound).baseType(); + Type bound2 = bound.map(toTypeVarMap).baseType(); List prevBounds = bounds.get(ib); for (Type b : prevBounds) { //check for redundancy - use strict version of isSameType on tvars @@ -1831,15 +1841,10 @@ notifyChange(EnumSet.of(ib)); } //where - Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") { + TypeMapping toTypeVarMap = new TypeMapping() { @Override - public Type apply(Type t) { - if (t.hasTag(UNDETVAR)) { - UndetVar uv = (UndetVar)t; - return uv.inst != null ? uv.inst : uv.qtype; - } else { - return t.map(this); - } + public Type visitUndetVar(UndetVar uv, Void _unused) { + return uv.inst != null ? uv.inst : uv.qtype; } }; @@ -2110,7 +2115,6 @@ public Type getEnclosingType() { return this; } public Type getReturnType() { return this; } public Type asSub(Symbol sym) { return this; } - public Type map(Mapping f) { return this; } public boolean isGenType(Type t) { return true; } public boolean isErroneous() { return true; } diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Sun Mar 29 09:21:15 2015 -0400 @@ -32,6 +32,8 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import java.util.function.BiPredicate; +import java.util.stream.Collector; import javax.tools.JavaFileObject; @@ -1766,10 +1768,11 @@ // public List cvarLowerBounds(List ts) { - return map(ts, cvarLowerBoundMapping); + return ts.map(cvarLowerBoundMapping); } - private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") { - public Type apply(Type t) { + private final TypeMapping cvarLowerBoundMapping = new TypeMapping() { + @Override + public Type visitCapturedType(CapturedType t, Void _unused) { return cvarLowerBound(t); } }; @@ -1879,9 +1882,15 @@ /** * Mapping to take element type of an arraytype */ - private Mapping elemTypeFun = new Mapping ("elemTypeFun") { - public Type apply(Type t) { - return elemtype(skipTypeVars(t, false)); + private TypeMapping elemTypeFun = new TypeMapping() { + @Override + public Type visitArrayType(ArrayType t, Void _unused) { + return t.elemtype; + } + + @Override + public Type visitTypeVar(TypeVar t, Void _unused) { + return visit(skipTypeVars(t, false)); } }; @@ -2177,7 +2186,7 @@ } } // where - private SimpleVisitor erasure = new SimpleVisitor() { + private TypeMapping erasure = new TypeMapping() { private Type combineMetadata(final Type ty, final TypeMetadata md) { if (!md.isEmpty()) { @@ -2202,8 +2211,8 @@ if (t.isPrimitive()) return t; /*fast special case*/ else { - Type erased = t.map(recurse ? erasureRecFun : erasureFun); - return combineMetadata(erased, t.getMetadata()); + //other cases already handled + return combineMetadata(t, t.getMetadata()); } } @@ -2223,23 +2232,10 @@ Type erased = erasure(t.bound, recurse); return combineMetadata(erased, t.getMetadata()); } - - @Override - public Type visitErrorType(ErrorType t, Boolean recurse) { - return t; - } }; - private Mapping erasureFun = new Mapping ("erasure") { - public Type apply(Type t) { return erasure(t); } - }; - - private Mapping erasureRecFun = new Mapping ("erasureRecursive") { - public Type apply(Type t) { return erasureRecursive(t); } - }; - public List erasure(List ts) { - return Type.map(ts, erasureFun); + return erasure.visit(ts, false); } public Type erasureRecursive(Type t) { @@ -2247,7 +2243,7 @@ } public List erasureRecursive(List ts) { - return Type.map(ts, erasureRecFun); + return erasure.visit(ts, true); } // @@ -3177,15 +3173,18 @@ * changing all recursive bounds from old to new list. */ public List newInstances(List tvars) { - List tvars1 = Type.map(tvars, newInstanceFun); + List tvars1 = tvars.map(newInstanceFun); for (List l = tvars1; l.nonEmpty(); l = l.tail) { TypeVar tv = (TypeVar) l.head; tv.bound = subst(tv.bound, tvars, tvars1); } return tvars1; } - private static final Mapping newInstanceFun = new Mapping("newInstanceFun") { - public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); } + private static final TypeMapping newInstanceFun = new TypeMapping() { + @Override + public TypeVar visitTypeVar(TypeVar t, Void _unused) { + return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); + } }; // @@ -3409,41 +3408,86 @@ } /** + * Collect types into a new closure (using a @code{ClosureHolder}) + */ + public Collector> closureCollector(boolean minClosure, BiPredicate shouldSkip) { + return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip), + ClosureHolder::add, + ClosureHolder::merge, + ClosureHolder::closure); + } + //where + class ClosureHolder { + List closure; + final boolean minClosure; + final BiPredicate shouldSkip; + + ClosureHolder(boolean minClosure, BiPredicate shouldSkip) { + this.closure = List.nil(); + this.minClosure = minClosure; + this.shouldSkip = shouldSkip; + } + + void add(Type type) { + closure = insert(closure, type, shouldSkip); + } + + ClosureHolder merge(ClosureHolder other) { + closure = union(closure, other.closure, shouldSkip); + return this; + } + + List closure() { + return minClosure ? closureMin(closure) : closure; + } + } + + BiPredicate basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym; + + /** * Insert a type in a closure */ - public List insert(List cl, Type t) { + public List insert(List cl, Type t, BiPredicate shouldSkip) { if (cl.isEmpty()) { return cl.prepend(t); - } else if (t.tsym == cl.head.tsym) { + } else if (shouldSkip.test(t, cl.head)) { return cl; } else if (t.tsym.precedes(cl.head.tsym, this)) { return cl.prepend(t); } else { // t comes after head, or the two are unrelated - return insert(cl.tail, t).prepend(cl.head); + return insert(cl.tail, t, shouldSkip).prepend(cl.head); } } + public List insert(List cl, Type t) { + return insert(cl, t, basicClosureSkip); + } + /** * Form the union of two closures */ - public List union(List cl1, List cl2) { + public List union(List cl1, List cl2, BiPredicate shouldSkip) { if (cl1.isEmpty()) { return cl2; } else if (cl2.isEmpty()) { return cl1; - } else if (cl1.head.tsym == cl2.head.tsym) { - return union(cl1.tail, cl2.tail).prepend(cl1.head); + } else if (shouldSkip.test(cl1.head, cl2.head)) { + return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head); } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) { - return union(cl1.tail, cl2).prepend(cl1.head); + return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) { - return union(cl1, cl2.tail).prepend(cl2.head); + return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head); } else { // unrelated types - return union(cl1.tail, cl2).prepend(cl1.head); + return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); } } + public List union(List cl1, List cl2) { + return union(cl1, cl2, basicClosureSkip); + } + /** * Intersect two closures */ diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Sun Mar 29 09:21:15 2015 -0400 @@ -40,11 +40,13 @@ import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.comp.DeferredAttr.AttrMode; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.FreeTypeListener; import com.sun.tools.javac.jvm.*; +import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; @@ -2871,6 +2873,16 @@ names.empty, List.of(fExpr.targets.head), ABSTRACT); if (csym != null) { chk.checkImplementations(env.tree, csym, csym); + try { + //perform an additional functional interface check on the synthetic class, + //as there may be spurious errors for raw targets - because of existing issues + //with membership and inheritance (see JDK-8074570). + csym.flags_field |= INTERFACE; + types.findDescriptorType(csym.type); + } catch (FunctionDescriptorLookupError err) { + resultInfo.checkContext.report(fExpr, + diags.fragment(Fragments.NoSuitableFunctionalIntfInst(fExpr.targets.head))); + } } } catch (Types.FunctionDescriptorLookupError ex) { JCDiagnostic cause = ex.getDiagnostic(); @@ -2942,7 +2954,7 @@ public void visitBinary(JCBinary tree) { // Attribute arguments. Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env)); - Type right = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.rhs, env)); + Type right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, env)); // Find operator. Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); Type owntype = types.createErrorType(tree.type); @@ -3722,7 +3734,7 @@ DeferredAttr.DeferredTypeMap checkDeferredMap = deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase); - argtypes = Type.map(argtypes, checkDeferredMap); + argtypes = argtypes.map(checkDeferredMap); if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { chk.warnUnchecked(env.tree.pos(), @@ -3730,7 +3742,7 @@ kindName(sym), sym.name, rs.methodArguments(sym.type.getParameterTypes()), - rs.methodArguments(Type.map(argtypes, checkDeferredMap)), + rs.methodArguments(argtypes.map(checkDeferredMap)), kindName(sym.location()), sym.location()); owntype = new MethodType(owntype.getParameterTypes(), @@ -3754,7 +3766,7 @@ return new Pair<>(sym, diag); } }; - List argtypes2 = Type.map(argtypes, + List argtypes2 = argtypes.map( rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, env.tree, sym, site, sym.name, argtypes2, typeargtypes); diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Sun Mar 29 09:21:15 2015 -0400 @@ -27,6 +27,7 @@ import com.sun.source.tree.LambdaExpressionTree.BodyKind; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Type.TypeMapping; import com.sun.tools.javac.comp.Resolve.ResolveError; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; @@ -44,7 +45,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.EnumMap; import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -300,13 +300,6 @@ } }; - DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() { - public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { - Assert.check(deferredAttrContext.mode == AttrMode.CHECK); - return dt.tree.type = Type.stuckType; - } - }; - /** * Policy for detecting stuck expressions. Different criteria might cause * an expression to be judged as stuck, depending on whether the check @@ -849,33 +842,24 @@ /** an empty deferred attribution context - all methods throw exceptions */ final DeferredAttrContext emptyDeferredAttrContext; - /** The AttrMode to descriptive name mapping */ - private static final EnumMap deferredTypeMapDescriptions; - static { - deferredTypeMapDescriptions = new EnumMap<>(AttrMode.class); - deferredTypeMapDescriptions.put(AttrMode.CHECK, "deferredTypeMap[CHECK]"); - deferredTypeMapDescriptions.put(AttrMode.SPECULATIVE, "deferredTypeMap[SPECULATIVE]"); - } - /** * Map a list of types possibly containing one or more deferred types * into a list of ordinary types. Each deferred type D is mapped into a type T, * where T is computed by retrieving the type that has already been * computed for D during a previous deferred attribution round of the given kind. */ - class DeferredTypeMap extends Type.Mapping { + class DeferredTypeMap extends TypeMapping { DeferredAttrContext deferredAttrContext; protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { - super(deferredTypeMapDescriptions.get(mode)); this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); } @Override - public Type apply(Type t) { + public Type visitType(Type t, Void _unused) { if (!t.hasTag(DEFERRED)) { - return t.map(this); + return super.visitType(t, null); } else { DeferredType dt = (DeferredType)t; return typeOf(dt); @@ -928,7 +912,7 @@ return chk.checkNonVoid(pos, super.check(pos, found)); } }); - return super.apply(dt); + return super.visit(dt); } } diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Sun Mar 29 09:21:15 2015 -0400 @@ -25,6 +25,7 @@ package com.sun.tools.javac.comp; +import com.sun.tools.javac.code.Type.TypeMapping; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.tree.TreeInfo; @@ -477,7 +478,7 @@ restype = syms.objectType; } - List paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step)); + List paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step)); List exType = spMethod != null ? spMethod.getThrownTypes() : List.of(syms.throwableType); // make it throw all exceptions @@ -495,9 +496,16 @@ (rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase); } - public Type apply(Type t) { - t = types.erasure(super.apply(t)); - if (t.hasTag(BOT)) + @Override + public Type visitClassType(ClassType t, Void aVoid) { + return types.erasure(t); + } + + @Override + public Type visitType(Type t, Void _unused) { + if (t.hasTag(DEFERRED)) { + return visit(super.visitType(t, null)); + } else if (t.hasTag(BOT)) // nulls type as the marker type Null (which has no instances) // infer as java.lang.Void for now t = types.boxedClass(syms.voidType).type; @@ -865,7 +873,8 @@ @Override public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { Infer infer = inferenceContext.infer(); - List boundList = uv.getBounds(InferenceBound.UPPER); + List boundList = uv.getBounds(InferenceBound.UPPER).stream() + .collect(infer.types.closureCollector(true, infer.types::isSameType)); List boundListTail = boundList.tail; while (boundList.nonEmpty()) { List tmpTail = boundListTail; @@ -2046,23 +2055,19 @@ List freetypeListeners = List.nil(); public InferenceContext(List inferencevars) { - this.undetvars = Type.map(inferencevars, fromTypeVarFun); + this.undetvars = inferencevars.map(fromTypeVarFun); this.inferencevars = inferencevars; } //where - Mapping fromTypeVarFun = new Mapping("fromTypeVarFunWithBounds") { - // mapping that turns inference variables into undet vars - public Type apply(Type t) { - if (t.hasTag(TYPEVAR)) { - TypeVar tv = (TypeVar)t; - if (tv.isCaptured()) { - return new CapturedUndetVar((CapturedType)tv, types); - } else { - return new UndetVar(tv, types); - } - } else { - return t.map(this); - } + TypeMapping fromTypeVarFun = new TypeMapping() { + @Override + public Type visitTypeVar(TypeVar tv, Void aVoid) { + return new UndetVar(tv, types); + } + + @Override + public Type visitCapturedType(CapturedType t, Void aVoid) { + return new CapturedUndetVar(t, types); } }; diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Sun Mar 29 09:21:15 2015 -0400 @@ -232,8 +232,7 @@ } } String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; - List argtypes2 = Type.map(argtypes, - deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); + List argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, mostSpecificPos, currentResolutionContext.step, methodArguments(argtypes2), @@ -2259,7 +2258,7 @@ (typeargtypes == null || !Type.isErroneous(typeargtypes)); } public List getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List argtypes) { - return Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); + return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); } }; diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Sun Mar 29 09:21:15 2015 -0400 @@ -56,6 +56,7 @@ import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.Kind.*; +import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.code.TypeTag.TYPEVAR; import static com.sun.tools.javac.jvm.ClassFile.*; @@ -2006,6 +2007,15 @@ } if (saveParameterNames) setParameterNames(m, type); + + if ((flags & VARARGS) != 0) { + final Type last = type.getParameterTypes().last(); + if (last == null || !last.hasTag(ARRAY)) { + m.flags_field &= ~VARARGS; + throw badClassFile("malformed.vararg.method", m); + } + } + return m; } diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Sun Mar 29 09:21:15 2015 -0400 @@ -1847,6 +1847,9 @@ compiler.misc.undecl.type.var=\ undeclared type variable: {0} +compiler.misc.malformed.vararg.method=\ + class file contains malformed variable arity method: {0} + compiler.misc.wrong.version=\ class file has wrong version {0}.{1}, should be {2}.{3} diff -r f07d88b6243c -r cdecfa325d0c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Sun Mar 29 09:21:15 2015 -0400 @@ -33,6 +33,7 @@ import java.util.AbstractCollection; import java.util.ListIterator; import java.util.NoSuchElementException; +import java.util.function.Function; import java.util.stream.Collector; /** A class for generic linked lists. Links are supposed to be @@ -417,6 +418,17 @@ } @SuppressWarnings("unchecked") + public List map(Function mapper) { + if (nonEmpty()) { + List tail1 = tail.map(mapper); + Z head1 = mapper.apply(head); + if (tail1 != tail || head1 != head) + return tail1.prepend(head1); + } + return (List)this; + } + + @SuppressWarnings("unchecked") public static List convert(Class klass, List list) { if (list == null) return null; diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/T8071847/T8071847.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T8071847/T8071847.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8071847 + * @summary Verify proper termination when instance initialization method uses invalid flags + * @compile T8071847.java + * @run main T8071847 +*/ + + +import java.io.*; +import java.util.*; + +public class T8071847 { + String testclass="invalidFlags.class"; + String testclassHexString = + "CAFEBABE00000031000D0A0003000A07000B07000C0100063C696E69743E0100" + + "03282956010004436F646501000F4C696E654E756D6265725461626C6501000A" + + "536F7572636546696C65010009546573742E6A6176610C0004000501000C696E" + + "76616C6964466C6167730100106A6176612F6C616E672F4F626A656374002000" + + "02000300000000000100A000040005000100060000001D00010001000000052A" + + "B70001B10000000100070000000600010000000100010008000000020009"; + + String testJavaFile = "testInvalidFlags.java"; + String testJavaSource ="public class testInvalidFlags extends invalidFlags {" + + "invalidFlags c = null;" + + "public testInvalidFlags() { c = new invalidFlags(); }" + + "public static void main(String... args) { " + + "new testInvalidFlags();}}"; + + public static void main(String[] args) throws Exception { + new T8071847().run(); + } + + public void run() throws IOException { + writeHexFile(testclass,testclassHexString); + writeTestFile(testJavaFile, testJavaSource); + javac(testJavaFile); + } + + File writeTestFile(String fname, String source) throws IOException { + File f = new File(fname); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(source); + out.close(); + return f; + } + + byte[] hexToByte(String str) { + char[] CA = str.toCharArray(); + byte[] byteArry = new byte[str.length()/2]; + int bi = 0; + for (int i = 0; i javacArgs = new ArrayList<>(); + javacArgs.addAll(Arrays.asList("-XDrawDiagnostics", "-cp", ".", "-d", ".", className)); + rc = com.sun.tools.javac.Main.compile( + javacArgs.toArray(new String[javacArgs.size()]),out); + out.close(); + if (rc > 1) { + System.out.println(sw.toString()); + throw new Error("javac " + className + " failed. rc=" + rc); + } + if (rc != 1 || !sw.toString().contains("compiler.misc.malformed.vararg.method")) + throw new RuntimeException("Unexpected output" + sw.toString()); + return sw.toString(); + } +} diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/diags/examples.not-yet.txt --- a/langtools/test/tools/javac/diags/examples.not-yet.txt Wed Mar 25 15:22:45 2015 +0000 +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Sun Mar 29 09:21:15 2015 -0400 @@ -87,6 +87,7 @@ compiler.misc.unable.to.access.file # ClassFile compiler.misc.undecl.type.var # ClassReader compiler.misc.unicode.str.not.supported # ClassReader +compiler.misc.malformed.vararg.method # ClassReader compiler.misc.verbose.retro # UNUSED compiler.misc.verbose.retro.with # UNUSED compiler.misc.verbose.retro.with.list # UNUSED diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/expression/BinopVoidTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/expression/BinopVoidTest.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8074148 + * @summary Attr.visitBinary flags error at wrong position + * + * @compile/fail/ref=BinopVoidTest.out -XDrawDiagnostics BinopVoidTest.java + */ + +class BinopVoidTest { + void foo() {} + int x = 10 + foo(); + int y = foo() + 10; + int z = foo() + foo(); +} diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/expression/BinopVoidTest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/expression/BinopVoidTest.out Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,5 @@ +BinopVoidTest.java:11:21: compiler.err.void.not.allowed.here +BinopVoidTest.java:12:16: compiler.err.void.not.allowed.here +BinopVoidTest.java:13:16: compiler.err.void.not.allowed.here +BinopVoidTest.java:13:24: compiler.err.void.not.allowed.here +4 errors diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/generics/inference/8048838/T8048838.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/8048838/T8048838.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8048838 + * @summary type inference performance regression + * @compile T8048838.java + */ +class T8048838 { + + + T1 foo(T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8, T9 x9, T10 x10, T11 x11, T12 x12, + T13 x13, T14 x14, T15 x15, T16 x16, T17 x17, T18 x18, T19 x19, T20 x20, T21 x21, T22 x22, + T23 x23, T24 x24, T25 x25, T26 x26, T27 x27, T28 x28, T29 x29, T30 x30, T31 x31, T32 x32, + T33 x33, T34 x34, T35 x35, T36 x36, T37 x37, T38 x38, T39 x39, T40 x40, T41 x41, T42 x42, + T43 x43, T44 x44, T45 x45, T46 x46, T47 x47, T48 x48, T49 x49, T50 x50, T51 x51, T52 x52, + T53 x53, T54 x54, T55 x55, T56 x56, T57 x57, T58 x58, T59 x59, T60 x60, T61 x61, T62 x62, + T63 x63, T64 x64, T65 x65, T66 x66, T67 x67, T68 x68, T69 x69, T70 x70, T71 x71, T72 x72, + T73 x73, T74 x74, T75 x75, T76 x76, T77 x77, T78 x78, T79 x79, T80 x80, T81 x81, T82 x82, + T83 x83, T84 x84, T85 x85, T86 x86, T87 x87, T88 x88, T89 x89, T90 x90, T91 x91, T92 x92, + T93 x93, T94 x94, T95 x95, T96 x96, T97 x97, T98 x98, T99 x99, T100 x100) { return null; } + + Object test() { + return foo(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, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100); // type inference expected + } +} diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/lambda/8074381/T8074381a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,33 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8074381 + * @summary java.lang.AssertionError during compiling + * @compile/fail/ref=T8074381a.out -XDrawDiagnostics T8074381a.java + */ +class T8074381a { + interface Sup { + boolean m(X x); + } + + interface Sub extends Sup { + boolean m(String s); + } + + void testRaw() { + Sub s1 = c -> true; + Sub s2 = Boolean::new; + Sub s3 = new Sub() { + @Override + public boolean m(String o) { return true; } + }; + } + + void testNonRaw() { + Sub s1 = c -> true; + Sub s2 = Boolean::new; + Sub s3 = new Sub() { + @Override + public boolean m(String o) { return true; } + }; + } +} diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/lambda/8074381/T8074381a.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.out Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,4 @@ +T8074381a.java:17:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) +T8074381a.java:18:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) +T8074381a.java:19:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup +3 errors diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/lambda/8074381/T8074381b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.java Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,44 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8074381 + * @summary java.lang.AssertionError during compiling + * @compile/fail/ref=T8074381b.out -XDrawDiagnostics T8074381b.java + */ +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +class T8074381b { + + @SuppressWarnings("unchecked") + public Invocation resolve(Handler handler) { + return new Invocation((t) -> handler.handle((String) t)); + } + + public static class Handler { + public void handle(String s) { + System.out.println(s); + } + } + + public static class Invocation { + public final ThrowingConsumer consumer; + + public Invocation(final ThrowingConsumer consumer) { + this.consumer = consumer; + } + } + + @FunctionalInterface + public interface ThrowingConsumer extends BiConsumer> { + @Override + default void accept(final T elem, final Consumer errorHandler) { + try { + acceptThrows(elem); + } catch (final Throwable e) { + errorHandler.accept(e); + } + } + + void acceptThrows(T elem) throws Throwable; + } +} diff -r f07d88b6243c -r cdecfa325d0c langtools/test/tools/javac/lambda/8074381/T8074381b.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.out Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,2 @@ +T8074381b.java:14:16: compiler.err.cant.apply.symbol: kindname.constructor, Invocation, T8074381b.ThrowingConsumer, @383, kindname.class, T8074381b.Invocation, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: T8074381b.ThrowingConsumer)) +1 error diff -r f07d88b6243c -r cdecfa325d0c make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Wed Mar 25 15:22:45 2015 +0000 +++ b/make/CompileJavaModules.gmk Sun Mar 29 09:21:15 2015 -0400 @@ -90,12 +90,16 @@ ################################################################################ +java.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' + +################################################################################ + java.datatransfer_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' java.datatransfer_COPY := flavormap.properties ################################################################################ -java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-missing,-reference '-Xdoclint/package:java.*,javax.*' +java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-missing,-reference '-Xdoclint/package:java.*,javax.*' java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties @@ -336,6 +340,7 @@ ################################################################################ +jdk.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:-com.sun.tools.*' jdk.compiler_COPY := javax.tools.JavaCompilerTool jdk.compiler_CLEAN_FILES := $(wildcard \ $(patsubst %, $(JDK_TOPDIR)/src/jdk.compiler/share/classes/%/*.properties, \ diff -r f07d88b6243c -r cdecfa325d0c make/Images.gmk --- a/make/Images.gmk Wed Mar 25 15:22:45 2015 +0000 +++ b/make/Images.gmk Sun Mar 29 09:21:15 2015 -0400 @@ -494,29 +494,16 @@ GCOV_FIND_EXPR := -type f -name "*.gcno" - ifeq ($(JVM_VARIANT_CLIENT), true) - $(eval $(call SetupCopyFiles,COPY_HOTSPOT_CLIENT_GCOV_GCNO, \ - SRC := $(HOTSPOT_OUTPUTDIR), \ - DEST := $(SYMBOLS_IMAGE_DIR)/gcov/hotspot/client, \ - FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR)/*compiler1/ $(GCOV_FIND_EXPR)), \ - FLATTEN := true)) - - SYMBOLS_TARGETS += $(COPY_HOTSPOT_CLIENT_GCOV_GCNO) - endif + $(eval $(call SetupCopyFiles,COPY_HOTSPOT_GCOV_GCNO, \ + SRC := $(OUTPUT_ROOT), \ + DEST := $(SYMBOLS_IMAGE_DIR)/gcov, \ + FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR) $(GCOV_FIND_EXPR)))) - ifeq ($(JVM_VARIANT_SERVER), true) - $(eval $(call SetupCopyFiles,COPY_HOTSPOT_SERVER_GCOV_GCNO, \ - SRC := $(HOTSPOT_OUTPUTDIR), \ - DEST := $(SYMBOLS_IMAGE_DIR)/gcov/hotspot/server, \ - FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR)/*compiler2/ $(GCOV_FIND_EXPR)), \ - FLATTEN := true)) - - SYMBOLS_TARGETS += $(COPY_HOTSPOT_SERVER_GCOV_GCNO) - endif + SYMBOLS_TARGETS += $(COPY_HOTSPOT_GCOV_GCNO) $(eval $(call SetupCopyFiles,COPY_JDK_GCOV_GCNO, \ - SRC := $(SUPPORT_OUTPUTDIR)/native, \ - DEST := $(SYMBOLS_IMAGE_DIR)/gcov/jdk, \ + SRC := $(OUTPUT_ROOT), \ + DEST := $(SYMBOLS_IMAGE_DIR)/gcov, \ FILES := $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/native $(GCOV_FIND_EXPR)))) SYMBOLS_TARGETS += $(COPY_JDK_GCOV_GCNO) diff -r f07d88b6243c -r cdecfa325d0c make/common/JavaCompilation.gmk --- a/make/common/JavaCompilation.gmk Wed Mar 25 15:22:45 2015 +0000 +++ b/make/common/JavaCompilation.gmk Sun Mar 29 09:21:15 2015 -0400 @@ -369,7 +369,7 @@ $(MKDIR) -p $$(@D) export LC_ALL=C ; ( $(CAT) $$< && $(ECHO) "" ) \ | $(SED) -e 's/\([^\\]\):/\1\\:/g' -e 's/\([^\\]\)=/\1\\=/g' \ - -e 's/\([^\\]\)!/\1\\!/g' -e 's/#.*/#/g' \ + -e 's/\([^\\]\)!/\1\\!/g' -e 's/^[ ]*#.*/#/g' \ | $(SED) -f "$(SRC_ROOT)/make/common/support/unicode2x.sed" \ | $(SED) -e '/^#/d' -e '/^$$$$/d' \ -e :a -e '/\\$$$$/N; s/\\\n//; ta' \ diff -r f07d88b6243c -r cdecfa325d0c make/common/NativeCompilation.gmk --- a/make/common/NativeCompilation.gmk Wed Mar 25 15:22:45 2015 +0000 +++ b/make/common/NativeCompilation.gmk Sun Mar 29 09:21:15 2015 -0400 @@ -60,7 +60,7 @@ -e 's|Note: including file: *||' \ -e 's|\\|/|g' \ -e 's|^\([a-zA-Z]\):|$(UNIX_PATH_PREFIX)/\1|g' \ - -e '/$(subst /,\/,$(TOPDIR))/!d' \ + -e '\|$(TOPDIR)|I !d' \ -e 's|$$$$| \\|g' \ # @@ -153,7 +153,7 @@ exit `cat $$($1_$2_DEP).exitvalue` $(RM) $$($1_$2_DEP).exitvalue ($(ECHO) $$@: \\ \ - && $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) > $$($1_$2_DEP) + && $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) | $(SORT) -u > $$($1_$2_DEP) endif # Create a dependency target file from the dependency file. # Solution suggested by http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ @@ -392,12 +392,6 @@ $1_EXTRA_CXXFLAGS+=$$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release) endif - # Pick up disabled warnings, if possible on this platform. - ifneq ($(DISABLE_WARNING_PREFIX),) - $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) - $1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) - endif - ifeq ($$($1_DEBUG_SYMBOLS), true) ifeq ($(ENABLE_DEBUG_SYMBOLS), true) ifdef OPENJDK @@ -415,6 +409,9 @@ endif endif + # If no C++ flags are explicitly set, default to using the C flags. + # After that, we can set additional C++ flags that should not interfere + # with the mechanism for copying the C flags by default. ifeq ($$($1_CXXFLAGS),) $1_CXXFLAGS:=$$($1_CFLAGS) endif @@ -427,6 +424,12 @@ $1_EXTRA_CXXFLAGS += $$(CXX_FLAG_REORDER) endif + # Pick up disabled warnings, if possible on this platform. + ifneq ($(DISABLE_WARNING_PREFIX),) + $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) + $1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) + endif + ifeq (NONE, $$($1_OPTIMIZATION)) $1_EXTRA_CFLAGS += $(C_O_FLAG_NONE) $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NONE) diff -r f07d88b6243c -r cdecfa325d0c nashorn/.hgtags --- a/nashorn/.hgtags Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/.hgtags Sun Mar 29 09:21:15 2015 -0400 @@ -288,3 +288,4 @@ fada76c29db9c792ad7127e674ef5337e15d2225 jdk9-b52 6cd23482ca9bd0caa6bfa6bf9064251178083d17 jdk9-b53 26460b897225010a4c7664eaff7a71f1156cacb3 jdk9-b54 +b2b332e64b7b2e06e25bccae9c0c0b585a03b4b5 jdk9-b55 diff -r f07d88b6243c -r cdecfa325d0c nashorn/samples/findwith.js --- a/nashorn/samples/findwith.js Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/samples/findwith.js Sun Mar 29 09:21:15 2015 -0400 @@ -52,7 +52,6 @@ var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1"); var parser = Parser.create("-scripting", "--const-as-var"); -var protoFound = false; function checkFile(file) { // print("checking " + file); @@ -92,7 +91,3 @@ } else { checkFile(file); } - -if (protoFound) { - print("__proto__ is non-standard. Use Object.get/setPrototypeOf instead"); -} diff -r f07d88b6243c -r cdecfa325d0c nashorn/samples/prettyprinter.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/prettyprinter.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This script is a AST pretty printer for ECMAScript. It uses + * Nashorn parser API to parser given script and uses tree visitor + * to pretty print the AST to stdout as a script string. + */ + +var File = Java.type("java.io.File"); +var file = arguments.length == 0? new File(__FILE__) : new File(arguments[0]); +if (! file.isFile()) { + print(arguments[0] + " is not a file"); + exit(1); +} + +// Java classes used +var ArrayAccess = Java.type("jdk.nashorn.api.tree.ArrayAccessTree"); +var Block = Java.type("jdk.nashorn.api.tree.BlockTree"); +var FunctionDeclaration = Java.type("jdk.nashorn.api.tree.FunctionDeclarationTree"); +var FunctionExpression = Java.type("jdk.nashorn.api.tree.FunctionExpressionTree"); +var Identifier = Java.type("jdk.nashorn.api.tree.IdentifierTree"); +var Kind = Java.type("jdk.nashorn.api.tree.Tree.Kind"); +var MemberSelect = Java.type("jdk.nashorn.api.tree.MemberSelectTree"); +var ObjectLiteral = Java.type("jdk.nashorn.api.tree.ObjectLiteralTree"); +var Parser = Java.type("jdk.nashorn.api.tree.Parser"); +var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1"); +var System = Java.type("java.lang.System"); + +// make a nashorn parser +var parser = Parser.create("-scripting", "--const-as-var"); + +// symbols for nashorn operators +var operatorSymbols = { + POSTFIX_INCREMENT: "++", + POSTFIX_DECREMENT: "--", + PREFIX_INCREMENT: "++", + PREFIX_DECREMENT: "--", + UNARY_PLUS: "+", + UNARY_MINUS: "-", + BITWISE_COMPLEMENT: "~", + LOGICAL_COMPLEMENT: "!", + DELETE: "delete ", + TYPEOF: "typeof ", + VOID: "void ", + COMMA: ",", + MULTIPLY: "*", + DIVIDE: "/", + REMINDER: "%", + PLUS: "+", + MINUS: "-", + LEFT_SHIFT: "<<", + RIGHT_SHIFT: ">>", + UNSIGNED_RIGHT_SHIFT: ">>>", + LESS_THAN: "<", + GREATER_THAN: ">", + LESS_THAN_EQUAL: "<=", + GREATER_THAN_EQUAL: ">=", + IN: "in", + EQUAL_TO: "==", + NOT_EQUAL_TO: "!=", + STRICT_EQUAL_TO: "===", + STRICT_NOT_EQUAL_TO: "!==", + AND: "&", + XOR: "^", + OR: "|", + CONDITIONAL_AND: "&&", + CONDITIONAL_OR: "||", + MULTIPLY_ASSIGNMENT: "*=", + DIVIDE_ASSIGNMENT: "/=", + REMINDER_ASSIGNMENT: "%=", + PLUS_ASSIGNMENT: "+=", + MINUS_ASSIGNMENT: "-=", + LEFT_SHIFT_ASSIGNMENT: "<<=", + RIGHT_SHIFT_ASSIGNMENT: ">>=", + UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: ">>>=", + AND_ASSIGNMENT: "&=", + XOR_ASSIGNMENT: "^=", + OR_ASSIGNMENT: "|=" +}; + +function operatorOf(kind) { + var name = kind.name(); + if (name in operatorSymbols) { + return operatorSymbols[name]; + } + throw "invalid operator: " + name; +} + +var gprint = print; + +function prettyPrint(file) { + var ast = parser.parse(file, gprint); + if (!ast) { + // failed to parse. don't print anything! + return; + } + + // AST visitor + var visitor; + // current indent level + var indentLevel = 0; + var out = System.out; + + function print(obj) { + out.print(String(obj)); + } + + function println(obj) { + obj? out.println(String(obj)) : out.println(); + } + + // semicolon and end-of-line + function eol() { + println(";"); + } + + // print indentation - 4 spaces per level + function indent() { + for (var i = 0; i < indentLevel; i++) { + // 4 spaces per indent level + print(" "); + } + } + + // escape string literals + function escapeString(str) { + // FIXME: incomplete, revisit again! + return str.replace(/[\\"']/g, '\\$&') + } + + // print a single statement (could be a block too) + function printStatement(stat, extra, end) { + if (stat instanceof Block) { + println(" {"); + printStatements(stat.statements, extra); + indent(); + print('}'); + typeof end != "undefined"? print(end) : println(); + } else { + println(); + indentLevel++; + try { + stat.accept(visitor, extra); + } finally { + indentLevel--; + } + } + } + + // print a statement list + function printStatements(stats, extra) { + indentLevel++; + try { + for each (var stat in stats) { + stat.accept(visitor, extra); + } + } finally { + indentLevel--; + } + } + + // function arguments, array literal elements. + function printCommaList(args, extra) { + var len = args.length; + for (var i = 0; i < len; i++) { + args[i].accept(visitor, extra); + if (i != len - 1) { + print(", "); + } + } + } + + // print function declarations and expressions + function printFunction(func, extra, end) { + // extra lines around function declarations for clarity + var funcDecl = (func instanceof FunctionDeclaration); + if (funcDecl) { + println(); + indent(); + } + print("function "); + if (func.name) { + print(func.name); + } + printFunctionBody(func, extra, end); + if (funcDecl) { + println(); + } + } + + // print function declaration/expression body + function printFunctionBody(func, extra, end) { + print('('); + var params = func.parameters; + if (params) { + printCommaList(params); + } + print(')'); + printStatement(func.body, extra, end); + } + + // print object literal property + function printProperty(node, extra, comma) { + var key = node.key; + var val = node.value; + var getter = node.getter; + var setter = node.setter; + + if (getter) { + print("get "); + } else if (setter) { + print("set "); + } + + if (typeof key == "string") { + print(key); + } else { + key.accept(visitor, extra); + } + + if (val) { + print(": "); + if (val instanceof FunctionExpression) { + printFunction(val, extra, comma? ',' : undefined); + } else { + val.accept(visitor, extra); + if (comma) print(','); + } + } else if (getter) { + printFunctionBody(getter, extra, comma? ',' : undefined); + } else if (setter) { + printFunctionBody(setter, extra, comma? ',' : undefined); + } + } + + + ast.accept(visitor = new (Java.extend(SimpleTreeVisitor)) { + visitAssignment: function(node, extra) { + node.variable.accept(visitor, extra); + print(" = "); + node.expression.accept(visitor, extra); + }, + + visitCompoundAssignment: function(node, extra) { + node.variable.accept(visitor, extra); + print(' ' + operatorOf(node.kind) + ' '); + node.expression.accept(visitor, extra); + }, + + visitBinary: function(node, extra) { + node.leftOperand.accept(visitor, extra); + print(' ' + operatorOf(node.kind) + ' '); + node.rightOperand.accept(visitor, extra); + }, + + visitBlock: function(node, extra) { + indent(); + println('{'); + printStatements(node.statements, extra); + indent(); + println('}'); + }, + + visitBreak: function(node, extra) { + indent(); + print("break"); + if (node.label) { + print(' ' + node.label); + } + eol(); + }, + + visitCase: function(node, extra) { + var expr = node.expression; + indent(); + if (expr) { + print("case "); + expr.accept(visitor, extra); + println(':'); + } else { + println("default:"); + } + + printStatements(node.statements, extra); + }, + + visitCatch: function(node, extra) { + indent(); + print("catch (" + node.parameter.name); + var cond = node.condition; + if (cond) { + print(" if "); + cond.accept(visitor, extra); + } + print(')'); + printStatement(node.block); + }, + + visitConditionalExpression: function(node, extra) { + print('('); + node.condition.accept(visitor, extra); + print(" ? "); + node.trueExpression.accept(visitor, extra); + print(" : "); + node.falseExpression.accept(visitor, extra); + print(')'); + }, + + visitContinue: function(node, extra) { + indent(); + print("continue"); + if (node.label) { + print(' ' + node.label); + } + eol(); + }, + + visitDebugger: function(node, extra) { + indent(); + print("debugger"); + eol(); + }, + + visitDoWhileLoop: function(node, extra) { + indent(); + print("do"); + printStatement(node.statement, extra); + indent(); + print("while ("); + node.condition.accept(visitor, extra); + print(')'); + eol(); + }, + + visitExpressionStatement: function(node, extra) { + indent(); + var expr = node.expression; + var objLiteral = expr instanceof ObjectLiteral; + if (objLiteral) { + print('('); + } + + expr.accept(visitor, extra); + if (objLiteral) { + print(')'); + } + eol(); + }, + + visitForLoop: function(node, extra) { + indent(); + print("for ("); + if (node.initializer) { + node.initializer.accept(visitor, extra); + } + + print(';'); + if (node.condition) { + node.condition.accept(visitor, extra); + } + print(';'); + if (node.update) { + node.update.accept(visitor, extra); + } + print(')'); + printStatement(node.statement); + }, + + visitForInLoop: function(node, extra) { + indent(); + print("for "); + if (node.forEach) { + print("each "); + } + print('('); + node.variable.accept(visitor, extra); + print(" in "); + node.expression.accept(visitor, extra); + print(')'); + printStatement(node.statement); + }, + + visitFunctionCall: function(node, extra) { + var func = node.functionSelect; + // We need parens around function selected + // in many non-simple cases. Eg. function + // expression created and called immediately. + // Such parens are not preserved in AST and so + // introduce here. + var simpleFunc = + (func instanceof ArrayAccess) || + (func instanceof Identifier) || + (func instanceof MemberSelect); + if (! simpleFunc) { + print('('); + } + func.accept(visitor, extra); + if (! simpleFunc) { + print(')'); + } + print('('); + printCommaList(node.arguments, extra); + print(')'); + }, + + visitFunctionDeclaration: function(node, extra) { + printFunction(node, extra); + }, + + visitFunctionExpression: function(node, extra) { + printFunction(node, extra); + }, + + visitIdentifier: function(node, extra) { + print(node.name); + }, + + visitIf: function(node, extra) { + indent(); + print("if ("); + node.condition.accept(visitor, extra); + print(')'); + printStatement(node.thenStatement); + var el = node.elseStatement; + if (el) { + indent(); + print("else"); + printStatement(el); + } + }, + + visitArrayAccess: function(node, extra) { + node.expression.accept(visitor, extra); + print('['); + node.index.accept(visitor, extra); + print(']'); + }, + + visitArrayLiteral: function(node, extra) { + print('['); + printCommaList(node.elements); + print(']'); + }, + + visitLabeledStatement: function(node, extra) { + indent(); + print(node.label); + print(':'); + printStatement(node.statement); + }, + + visitLiteral: function(node, extra) { + var val = node.value; + if (typeof val == "string") { + print("'" + escapeString(val) + "'"); + } else { + print(val); + } + }, + + visitParenthesized: function(node, extra) { + print('('); + node.expression.accept(visitor, extra); + print(')'); + }, + + visitReturn: function(node, extra) { + indent(); + print("return"); + if (node.expression) { + print(' '); + node.expression.accept(visitor, extra); + } + eol(); + }, + + visitMemberSelect: function(node, extra) { + node.expression.accept(visitor, extra); + print('.' + node.identifier); + }, + + visitNew: function(node, extra) { + print("new "); + node.constructorExpression.accept(visitor, extra); + }, + + visitObjectLiteral: function(node, extra) { + println('{'); + indentLevel++; + try { + var props = node.properties; + var len = props.length; + for (var p = 0; p < len; p++) { + var last = (p == len - 1); + indent(); + printProperty(props[p], extra, !last); + println(); + } + } finally { + indentLevel--; + } + indent(); + print('}'); + }, + + visitRegExpLiteral: function(node, extra) { + print('/' + node.pattern + '/'); + print(node.options); + }, + + visitEmptyStatement: function(node, extra) { + indent(); + eol(); + }, + + visitSwitch: function(node, extra) { + indent(); + print("switch ("); + node.expression.accept(visitor, extra); + println(") {"); + indentLevel++; + try { + for each (var c in node.cases) { + c.accept(visitor, extra); + } + } finally { + indentLevel--; + } + indent(); + println('}'); + }, + + visitThrow: function(node, extra) { + indent(); + print("throw "); + node.expression.accept(visitor, extra); + eol(); + }, + + visitCompilationUnit: function(node, extra) { + for each (var stat in node.sourceElements) { + stat.accept(visitor, extra); + } + }, + + visitTry: function(node, extra) { + indent(); + print("try"); + printStatement(node.block); + var catches = node.catches; + for each (var c in catches) { + c.accept(visitor, extra); + } + var finallyBlock = node.finallyBlock; + if (finallyBlock) { + indent(); + print("finally"); + printStatement(finallyBlock); + } + }, + + visitInstanceOf: function(node, extra) { + node.expression.accept(visitor, extra); + print(" instanceof "); + node.type.accept(visitor, extra); + }, + + visitUnary: function(node, extra) { + var kind = node.kind; + var prefix = kind != Kind.POSTFIX_INCREMENT && kind != Kind.POSTFIX_DECREMENT; + if (prefix) { + print(operatorOf(kind)); + } + node.expression.accept(visitor, extra); + if (!prefix) { + print(operatorOf(kind)); + } + }, + + visitVariable: function(node, extra) { + indent(); + print("var " + node.name); + var init = node.initializer; + if (init) { + print(" = "); + if (init instanceof FunctionExpression) { + printFunction(init, extra, ""); + } else { + init.accept(visitor, extra); + } + } + eol(); + }, + + visitWhileLoop: function(node, extra) { + indent(); + print("while ("); + node.condition.accept(visitor, extra); + print(')'); + printStatement(node.statement); + }, + + visitWith: function(node, extra) { + indent(); + print("with ("); + node.scope.accept(visitor, extra); + print(')'); + printStatement(node.statement); + } + }, null); +} + +prettyPrint(file); diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java Sun Mar 29 09:21:15 2015 -0400 @@ -44,6 +44,7 @@ * * @return the condition expression */ + @Override ExpressionTree getCondition(); /** @@ -51,5 +52,6 @@ * * @return the statement */ + @Override StatementTree getStatement(); } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java Sun Mar 29 09:21:15 2015 -0400 @@ -57,6 +57,7 @@ * * @return the statement */ + @Override StatementTree getStatement(); /** diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -43,7 +43,7 @@ assert node.getInit() instanceof FunctionNode : "function expected"; funcNode = (FunctionNode)node.getInit(); assert funcNode.isDeclared() : "function declaration expected"; - funcName = node.getName().getName(); + funcName = funcNode.isAnonymous()? null : node.getName().getName(); this.params = params; this.body = body; } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java Sun Mar 29 09:21:15 2015 -0400 @@ -25,6 +25,7 @@ package jdk.nashorn.api.tree; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -92,7 +93,7 @@ final Block body = node.getBody(); return new CompilationUnitTreeImpl(node, - translateStats(body != null? body.getStatements() : null)); + translateStats(body != null? getOrderedStatements(body.getStatements()) : null)); } @Override @@ -103,25 +104,7 @@ @Override public boolean enterBlock(final Block block) { - // FIXME: revisit this! - if (block.isSynthetic()) { - final int statCount = block.getStatementCount(); - switch (statCount) { - case 0: { - final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish()); - curStat = new EmptyStatementTreeImpl(emptyNode); - return false; - } - case 1: { - curStat = translateStat(block.getStatements().get(0)); - return false; - } - } - } - - curStat = new BlockTreeImpl(block, - translateStats(block.getStatements())); - return false; + return handleBlock(block, false); } @Override @@ -245,7 +228,7 @@ final List paramTrees = translateExprs(functionNode.getParameters()); - final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody()); + final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody(), true); curExpr = new FunctionExpressionTreeImpl(functionNode, paramTrees, blockTree); return false; @@ -420,7 +403,7 @@ final List paramTrees = translateExprs(funcNode.getParameters()); - final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody()); + final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody(), true); curStat = new FunctionDeclarationTreeImpl(varNode, paramTrees, blockTree); } else { curStat = new VariableTreeImpl(varNode, translateExpr(initNode)); @@ -453,14 +436,51 @@ } private StatementTree translateBlock(final Block blockNode) { + return translateBlock(blockNode, false); + } + + private StatementTree translateBlock(final Block blockNode, final boolean sortStats) { if (blockNode == null) { return null; } curStat = null; - blockNode.accept(this); + handleBlock(blockNode, sortStats); return curStat; } + private boolean handleBlock(final Block block, final boolean sortStats) { + // FIXME: revisit this! + if (block.isSynthetic()) { + final int statCount = block.getStatementCount(); + switch (statCount) { + case 0: { + final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish()); + curStat = new EmptyStatementTreeImpl(emptyNode); + return false; + } + case 1: { + curStat = translateStat(block.getStatements().get(0)); + return false; + } + default: { + // fall through + break; + } + } + } + + final List stats = block.getStatements(); + curStat = new BlockTreeImpl(block, + translateStats(sortStats? getOrderedStatements(stats) : stats)); + return false; + } + + private List getOrderedStatements(final List stats) { + final List statList = new ArrayList<>(stats); + statList.sort(Comparator.comparingInt(Node::getSourceOrder)); + return statList; + } + private List translateStats(final List stats) { if (stats == null) { return null; @@ -511,7 +531,7 @@ return curStat; } - private IdentifierTree translateIdent(final IdentNode ident) { + private static IdentifierTree translateIdent(final IdentNode ident) { return new IdentifierTreeImpl(ident); } } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java Sun Mar 29 09:21:15 2015 -0400 @@ -139,7 +139,7 @@ } } - private CompilationUnitTree translate(final FunctionNode node) { + private static CompilationUnitTree translate(final FunctionNode node) { return new IRTranslator().translate(node); } } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java Sun Mar 29 09:21:15 2015 -0400 @@ -43,6 +43,7 @@ * * @return the condition expression */ + @Override ExpressionTree getCondition(); /** @@ -50,5 +51,6 @@ * * @return the statement contained */ + @Override StatementTree getStatement(); } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Sun Mar 29 09:21:15 2015 -0400 @@ -183,6 +183,17 @@ return start; } + /** + * Integer to sort nodes in source order. This order is + * used by parser API to sort statements in correct order. + * By default, this is the start position of this node. + * + * @return int code to sort this node. + */ + public int getSourceOrder() { + return getStart(); + } + @Override protected Object clone() { try { diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Sun Mar 29 09:21:15 2015 -0400 @@ -45,6 +45,13 @@ /** Is this a var statement (as opposed to a "var" in a for loop statement) */ private final int flags; + /** + * source order id to be used for this node. If this is -1, then we + * the default which is start position of this node. See also the + * method Node::getSourceOrder. + */ + private final int sourceOrder; + /** Flag for ES6 LET declaration */ public static final int IS_LET = 1 << 0; @@ -71,6 +78,7 @@ private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) { super(varNode); + this.sourceOrder = -1; this.name = init == null ? name : name.setIsInitializedHere(); this.init = init; this.flags = flags; @@ -79,22 +87,42 @@ /** * Constructor * - * @param lineNumber line number - * @param token token - * @param finish finish - * @param name name of variable - * @param init init node or null if just a declaration - * @param flags flags + * @param lineNumber line number + * @param token token + * @param finish finish + * @param name name of variable + * @param init init node or null if just a declaration + * @param flags flags */ public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init, final int flags) { + this(lineNumber, token, -1, finish, name, init, flags); + } + + /** + * Constructor + * + * @param lineNumber line number + * @param token token + * @param sourceOrder source order + * @param finish finish + * @param name name of variable + * @param init init node or null if just a declaration + * @param flags flags + */ + public VarNode(final int lineNumber, final long token, final int sourceOrder, final int finish, final IdentNode name, final Expression init, final int flags) { super(lineNumber, token, finish); - + this.sourceOrder = sourceOrder; this.name = init == null ? name : name.setIsInitializedHere(); this.init = init; this.flags = flags; } @Override + public int getSourceOrder() { + return sourceOrder == -1? super.getSourceOrder() : sourceOrder; + } + + @Override public boolean isAssignment() { return hasInit(); } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java Sun Mar 29 09:21:15 2015 -0400 @@ -26,7 +26,9 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + import java.nio.ByteBuffer; + import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -101,7 +103,7 @@ } if (args.length == 0) { - throw new RuntimeException("missing length argument"); + return new NativeArrayBuffer(0); } return new NativeArrayBuffer(JSType.toInt32(args[0])); diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Sun Mar 29 09:21:15 2015 -0400 @@ -1066,6 +1066,10 @@ * @param isStatement True if a statement (not used in a FOR.) */ private List variableStatement(final TokenType varType, final boolean isStatement) { + return variableStatement(varType, isStatement, -1); + } + + private List variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) { // VAR tested in caller. next(); @@ -1104,7 +1108,7 @@ } // Allocate var node. - final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags); + final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name.setIsDeclaredHere(), init, varFlags); vars.add(var); appendStatement(var); @@ -1211,6 +1215,10 @@ private void forStatement() { final long forToken = token; final int forLine = line; + // start position of this for statement. This is used + // for sort order for variables declared in the initialzer + // part of this 'for' statement (if any). + final int forStart = Token.descPosition(forToken); // When ES6 for-let is enabled we create a container block to capture the LET. final int startLine = start; final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null; @@ -1243,7 +1251,7 @@ switch (type) { case VAR: // Var declaration captured in for outer block. - vars = variableStatement(type, false); + vars = variableStatement(type, false, forStart); break; case SEMICOLON: break; @@ -1253,12 +1261,12 @@ flags |= ForNode.PER_ITERATION_SCOPE; } // LET/CONST declaration captured in container block created above. - vars = variableStatement(type, false); + vars = variableStatement(type, false, forStart); break; } if (env._const_as_var && type == CONST) { // Var declaration captured in for outer block. - vars = variableStatement(TokenType.VAR, false); + vars = variableStatement(TokenType.VAR, false, forStart); break; } diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Sun Mar 29 09:21:15 2015 -0400 @@ -27,7 +27,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; - import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -595,7 +594,7 @@ * switchpoint has been invalidated by a {@code RewriteException} triggered on another thread for this function. * This is not a problem, though, as these switch points are always used to produce call sites that fall back to * relinking when they are invalidated, and in this case the execution will end up here again. What this method - * basically does is reduce such busy-loop relinking while the function is being recompiled on a different thread. + * basically does is minimize such busy-loop relinking while the function is being recompiled on a different thread. * @param invocationSupplier the supplier that constructs the actual invocation method handle; should use the * {@code CompiledFunction} method itself in some capacity. * @return a tuple object containing the method handle as created by the supplier and an optimistic assumptions @@ -603,27 +602,20 @@ * function can't be further deoptimized). */ private synchronized HandleAndAssumptions getValidOptimisticInvocation(final Supplier invocationSupplier) { - for(int i = 0; i < 2; ++i) { + for(;;) { final MethodHandle handle = invocationSupplier.get(); final SwitchPoint assumptions = canBeDeoptimized() ? optimismInfo.optimisticAssumptions : null; - if(i == 0 && assumptions != null && assumptions.hasBeenInvalidated()) { + if(assumptions != null && assumptions.hasBeenInvalidated()) { // We can be in a situation where one thread is in the middle of a deoptimizing compilation when we hit // this and thus, it has invalidated the old switch point, but hasn't created the new one yet. Note that // the behavior of invalidating the old switch point before recompilation, and only creating the new one - // after recompilation is by design. If we didn't wait here, we would be busy looping through the - // fallback path of the invalidated switch point, relinking the call site again with the same - // invalidated switch point, invoking the fallback, etc. stealing CPU cycles from the recompilation - // task we're dependent on. This can still happen if the switch point gets invalidated after we grabbed - // it here, in which case we'll indeed do one busy relink immediately. - // On the other hand, in order to avoid a rare livelock, we aren't doing an infinite loop, and we - // aren't wait()-ing indefinitely. We'll do at most one, at most 1000ms long wait after which we'll - // return the current handle even if it's invalidated (and which'll then trigger one loop through the - // relink mechanism). We therefore strike a balance between busy looping and a livelock risk by making - // sure that there's at most one iteration of busy loop per second. It is theoretically possible to - // correctly implement this without ever risking a livelock, but using this heuristic we eliminate the - // chance of the livelock, while still maintaining a good enough busy-looping prevention. + // after recompilation is by design. If we didn't wait here for the recompilation to complete, we would + // be busy looping through the fallback path of the invalidated switch point, relinking the call site + // again with the same invalidated switch point, invoking the fallback, etc. stealing CPU cycles from + // the recompilation task we're dependent on. This can still happen if the switch point gets invalidated + // after we grabbed it here, in which case we'll indeed do one busy relink immediately. try { - wait(1000L); + wait(); } catch (final InterruptedException e) { // Intentionally ignored. There's nothing meaningful we can do if we're interrupted } @@ -631,7 +623,6 @@ return new HandleAndAssumptions(handle, assumptions); } } - throw new AssertionError(); // never reached } private static void relinkComposableInvoker(final CallSite cs, final CompiledFunction inv, final boolean constructor) { diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Sun Mar 29 09:21:15 2015 -0400 @@ -330,12 +330,15 @@ * Indicate that proto itself has changed in hierarchy somewhere. */ synchronized void invalidateAllProtoGetSwitchPoints() { - if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) { - if (Context.DEBUG) { - protoInvalidations += protoGetSwitches.size(); + if (protoGetSwitches != null) { + final int size = protoGetSwitches.size(); + if (size > 0) { + if (Context.DEBUG) { + protoInvalidations += size; + } + SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size])); + protoGetSwitches.clear(); } - SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()])); - protoGetSwitches.clear(); } } @@ -375,7 +378,8 @@ } } - // Update the free slots bitmap for a property that has been deleted and/or added. + // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized + // as it is always invoked on a newly created instance. private void updateFreeSlots(final Property oldProperty, final Property newProperty) { // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications. boolean freeSlotsCloned = false; @@ -425,7 +429,7 @@ * * @return New {@link PropertyMap} with {@link Property} added. */ - public PropertyMap addProperty(final Property property) { + public synchronized PropertyMap addProperty(final Property property) { if (listeners != null) { listeners.propertyAdded(property); } @@ -434,9 +438,9 @@ if (newMap == null) { final PropertyHashMap newProperties = properties.immutableAdd(property); newMap = new PropertyMap(this, newProperties); - addToHistory(property, newMap); newMap.updateFlagsAndBoundaries(property); newMap.updateFreeSlots(null, property); + addToHistory(property, newMap); } return newMap; @@ -449,7 +453,7 @@ * * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found. */ - public PropertyMap deleteProperty(final Property property) { + public synchronized PropertyMap deleteProperty(final Property property) { if (listeners != null) { listeners.propertyDeleted(property); } @@ -881,8 +885,7 @@ * @param newProto New prototype object to replace oldProto. * @return New {@link PropertyMap} with prototype changed. */ - public PropertyMap changeProto(final ScriptObject newProto) { - + public synchronized PropertyMap changeProto(final ScriptObject newProto) { final PropertyMap nextMap = checkProtoHistory(newProto); if (nextMap != null) { return nextMap; diff -r f07d88b6243c -r cdecfa325d0c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Mar 25 15:22:45 2015 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Sun Mar 29 09:21:15 2015 -0400 @@ -109,7 +109,10 @@ */ public static void main(final String[] args) { try { - System.exit(main(System.in, System.out, System.err, args)); + final int exitCode = main(System.in, System.out, System.err, args); + if (exitCode != SUCCESS) { + System.exit(exitCode); + } } catch (final IOException e) { System.err.println(e); //bootstrapping, Context.err may not exist System.exit(IO_ERROR); diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/basic/JDK-8075090.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8075090.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8075090: Add tests for the basic failure of try/finally compilation + * + * @test + * @run + */ + +(function() { + var finallyExpected = false; + try { + for(var i = 0; i < 2; ++i) { + if(i == 1) { + continue; + } + } + finallyExpected = true; + } finally { + Assert.assertTrue(finallyExpected); + } +})(); + +(function() { + var finallyExpected = false; + try { + for(var i = 0; i < 2; ++i) { + if(i == 1) { + break; + } + } + finallyExpected = true; + } finally { + Assert.assertTrue(finallyExpected); + } +})(); + +(function() { + var finallyExpected = false; + try { + L1: { + if ((function(){return true})()) { + break L1; + } + Assert.fail(); // unreachable + } + finallyExpected = true; + } finally { + Assert.assertTrue(finallyExpected); + } +})(); diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/basic/JDK-8075207.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8075207.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8075207: Nashorn parser API returns StatementTree objects in out of order + * + * @test + * @option -scripting + * @run + */ + +var Parser = Java.type("jdk.nashorn.api.tree.Parser"); +var ExpressionStatementTree = Java.type("jdk.nashorn.api.tree.ExpressionStatementTree"); +var FunctionDeclarationTree = Java.type("jdk.nashorn.api.tree.FunctionDeclarationTree"); +var VariableTree = Java.type("jdk.nashorn.api.tree.VariableTree"); + +var parser = Parser.create(); + +var ast = parser.parse("hello.js", <>= 314; +xyz >>>= 314; +xyz &= 314; +xyz ^= 314; +xyz |= 314; + +EOF + + +parse("assignmentExpr.js", code, "-nse", new (Java.extend(visitor, { + visitCompoundAssignment : function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,189 @@ +[ + { + "expression": { + "endPosition": "10", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "7" + }, + "endPosition": "10", + "kind": "PLUS_ASSIGNMENT", + "variable": { + "endPosition": "3", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "0" + }, + "startPosition": "0" + }, + { + "expression": { + "endPosition": "22", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "19" + }, + "endPosition": "22", + "kind": "MINUS_ASSIGNMENT", + "variable": { + "endPosition": "15", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "12" + }, + "startPosition": "12" + }, + { + "expression": { + "endPosition": "34", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "31" + }, + "endPosition": "34", + "kind": "MULTIPLY_ASSIGNMENT", + "variable": { + "endPosition": "27", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "24" + }, + "startPosition": "24" + }, + { + "expression": { + "endPosition": "46", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "43" + }, + "endPosition": "46", + "kind": "DIVIDE_ASSIGNMENT", + "variable": { + "endPosition": "39", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "36" + }, + "startPosition": "36" + }, + { + "expression": { + "endPosition": "58", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "55" + }, + "endPosition": "58", + "kind": "REMAINDER_ASSIGNMENT", + "variable": { + "endPosition": "51", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "48" + }, + "startPosition": "48" + }, + { + "expression": { + "endPosition": "71", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "68" + }, + "endPosition": "71", + "kind": "LEFT_SHIFT_ASSIGNMENT", + "variable": { + "endPosition": "63", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "60" + }, + "startPosition": "60" + }, + { + "expression": { + "endPosition": "84", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "81" + }, + "endPosition": "84", + "kind": "RIGHT_SHIFT_ASSIGNMENT", + "variable": { + "endPosition": "76", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "73" + }, + "startPosition": "73" + }, + { + "expression": { + "endPosition": "98", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "95" + }, + "endPosition": "98", + "kind": "UNSIGNED_RIGHT_SHIFT_ASSIGNMENT", + "variable": { + "endPosition": "89", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "86" + }, + "startPosition": "86" + }, + { + "expression": { + "endPosition": "110", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "107" + }, + "endPosition": "110", + "kind": "AND_ASSIGNMENT", + "variable": { + "endPosition": "103", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "100" + }, + "startPosition": "100" + }, + { + "expression": { + "endPosition": "122", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "119" + }, + "endPosition": "122", + "kind": "XOR_ASSIGNMENT", + "variable": { + "endPosition": "115", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "112" + }, + "startPosition": "112" + }, + { + "expression": { + "endPosition": "134", + "kind": "NUMBER_LITERAL", + "value": "314", + "startPosition": "131" + }, + "endPosition": "134", + "kind": "OR_ASSIGNMENT", + "variable": { + "endPosition": "127", + "kind": "IDENTIFIER", + "name": "xyz", + "startPosition": "124" + }, + "startPosition": "124" + } +] diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/binaryExpr.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Tests to check representation binary expression tree. + * + * @bug 8068306 + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + +var code = <> b; +a >>> b; +a < b; +a > b; +a <= b; +a >= b; +a instanceof b; +a == b; +a != b; +a === b; +a !== b; +a & b; +a ^ b; +a | b; +a && b; +a || b; + +EOF + + +parse("binaryExpr.js", code, "-nse", new (Java.extend(visitor, { + visitBinary : function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,359 @@ +[ + { + "leftOperand": { + "endPosition": "1", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "0" + }, + "endPosition": "5", + "kind": "MULTIPLY", + "rightOperand": { + "endPosition": "5", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "4" + }, + "startPosition": "0" + }, + { + "leftOperand": { + "endPosition": "7", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "6" + }, + "endPosition": "11", + "kind": "DIVIDE", + "rightOperand": { + "endPosition": "11", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "10" + }, + "startPosition": "6" + }, + { + "leftOperand": { + "endPosition": "14", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "13" + }, + "endPosition": "18", + "kind": "REMAINDER", + "rightOperand": { + "endPosition": "18", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "17" + }, + "startPosition": "13" + }, + { + "leftOperand": { + "endPosition": "21", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "20" + }, + "endPosition": "25", + "kind": "PLUS", + "rightOperand": { + "endPosition": "25", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "24" + }, + "startPosition": "20" + }, + { + "leftOperand": { + "endPosition": "28", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "27" + }, + "endPosition": "32", + "kind": "MINUS", + "rightOperand": { + "endPosition": "32", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "31" + }, + "startPosition": "27" + }, + { + "leftOperand": { + "endPosition": "35", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "34" + }, + "endPosition": "40", + "kind": "LEFT_SHIFT", + "rightOperand": { + "endPosition": "40", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "39" + }, + "startPosition": "34" + }, + { + "leftOperand": { + "endPosition": "43", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "42" + }, + "endPosition": "48", + "kind": "RIGHT_SHIFT", + "rightOperand": { + "endPosition": "48", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "47" + }, + "startPosition": "42" + }, + { + "leftOperand": { + "endPosition": "51", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "50" + }, + "endPosition": "57", + "kind": "UNSIGNED_RIGHT_SHIFT", + "rightOperand": { + "endPosition": "57", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "56" + }, + "startPosition": "50" + }, + { + "leftOperand": { + "endPosition": "60", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "59" + }, + "endPosition": "64", + "kind": "LESS_THAN", + "rightOperand": { + "endPosition": "64", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "63" + }, + "startPosition": "59" + }, + { + "leftOperand": { + "endPosition": "67", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "66" + }, + "endPosition": "71", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "71", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "70" + }, + "startPosition": "66" + }, + { + "leftOperand": { + "endPosition": "74", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "73" + }, + "endPosition": "79", + "kind": "LESS_THAN_EQUAL", + "rightOperand": { + "endPosition": "79", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "78" + }, + "startPosition": "73" + }, + { + "leftOperand": { + "endPosition": "82", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "81" + }, + "endPosition": "87", + "kind": "GREATER_THAN_EQUAL", + "rightOperand": { + "endPosition": "87", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "86" + }, + "startPosition": "81" + }, + { + "leftOperand": { + "endPosition": "106", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "105" + }, + "endPosition": "111", + "kind": "EQUAL_TO", + "rightOperand": { + "endPosition": "111", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "110" + }, + "startPosition": "105" + }, + { + "leftOperand": { + "endPosition": "114", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "113" + }, + "endPosition": "119", + "kind": "NOT_EQUAL_TO", + "rightOperand": { + "endPosition": "119", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "118" + }, + "startPosition": "113" + }, + { + "leftOperand": { + "endPosition": "122", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "121" + }, + "endPosition": "128", + "kind": "STRICT_EQUAL_TO", + "rightOperand": { + "endPosition": "128", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "127" + }, + "startPosition": "121" + }, + { + "leftOperand": { + "endPosition": "131", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "130" + }, + "endPosition": "137", + "kind": "STRICT_NOT_EQUAL_TO", + "rightOperand": { + "endPosition": "137", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "136" + }, + "startPosition": "130" + }, + { + "leftOperand": { + "endPosition": "140", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "139" + }, + "endPosition": "144", + "kind": "AND", + "rightOperand": { + "endPosition": "144", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "143" + }, + "startPosition": "139" + }, + { + "leftOperand": { + "endPosition": "147", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "146" + }, + "endPosition": "151", + "kind": "XOR", + "rightOperand": { + "endPosition": "151", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "150" + }, + "startPosition": "146" + }, + { + "leftOperand": { + "endPosition": "154", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "153" + }, + "endPosition": "158", + "kind": "OR", + "rightOperand": { + "endPosition": "158", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "157" + }, + "startPosition": "153" + }, + { + "leftOperand": { + "endPosition": "161", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "160" + }, + "endPosition": "166", + "kind": "CONDITIONAL_AND", + "rightOperand": { + "endPosition": "166", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "165" + }, + "startPosition": "160" + }, + { + "leftOperand": { + "endPosition": "169", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "168" + }, + "endPosition": "174", + "kind": "CONDITIONAL_OR", + "rightOperand": { + "endPosition": "174", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "173" + }, + "startPosition": "168" + } +] diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/block.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/block.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Tests to check representation block tree. + * + * @bug 8068306 + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + +var code = < 20) + +do call();while(NaN) + +EOF + +parse("dowhile.js", code, "-nse", new (Java.extend(visitor, { + visitDoWhileLoop : function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,169 @@ +[ + { + "condition": { + "endPosition": "18", + "kind": "BOOLEAN_LITERAL", + "value": "false", + "startPosition": "13" + }, + "endPosition": "19", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "6", + "kind": "BLOCK", + "statements": [], + "startPosition": "4" + }, + "startPosition": "1" + }, + { + "condition": { + "endPosition": "42", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "38" + }, + "endPosition": "43", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "31", + "kind": "BLOCK", + "statements": [ + { + "endPosition": "30", + "kind": "BREAK", + "label": "null", + "startPosition": "24" + } + ], + "startPosition": "23" + }, + "startPosition": "20" + }, + { + "condition": { + "leftOperand": { + "endPosition": "76", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "75" + }, + "endPosition": "81", + "kind": "EQUAL_TO", + "rightOperand": { + "endPosition": "81", + "kind": "NUMBER_LITERAL", + "value": "2", + "startPosition": "80" + }, + "startPosition": "75" + }, + "endPosition": "82", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "68", + "kind": "BLOCK", + "statements": [ + { + "endPosition": "67", + "kind": "BREAK", + "label": "label", + "startPosition": "55" + } + ], + "startPosition": "54" + }, + "startPosition": "51" + }, + { + "condition": { + "leftOperand": { + "leftOperand": { + "endPosition": "112", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "111" + }, + "endPosition": "116", + "kind": "PLUS", + "rightOperand": { + "endPosition": "116", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "115" + }, + "startPosition": "111" + }, + "endPosition": "121", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "121", + "kind": "NUMBER_LITERAL", + "value": "20", + "startPosition": "119" + }, + "startPosition": "111" + }, + "endPosition": "122", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "105", + "kind": "BLOCK", + "statements": [ + { + "condition": { + "endPosition": "103", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "101", + "kind": "IDENTIFIER", + "name": "func1", + "startPosition": "96" + }, + "arguments": [], + "startPosition": "96" + }, + "endPosition": "104", + "kind": "DO_WHILE_LOOP", + "statement": { + "endPosition": "90", + "kind": "BLOCK", + "statements": [], + "startPosition": "88" + }, + "startPosition": "86" + } + ], + "startPosition": "85" + }, + "startPosition": "83" + }, + { + "condition": { + "endPosition": "143", + "kind": "IDENTIFIER", + "name": "NaN", + "startPosition": "140" + }, + "endPosition": "144", + "kind": "DO_WHILE_LOOP", + "statement": { + "expression": { + "endPosition": "133", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "131", + "kind": "IDENTIFIER", + "name": "call", + "startPosition": "127" + }, + "arguments": [], + "startPosition": "127" + }, + "endPosition": "133", + "kind": "EXPRESSION_STATEMENT", + "startPosition": "127" + }, + "startPosition": "124" + } +] diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/empty.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/empty.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Tests to check representation empty tree. + * + * @test + * @bug 8068306 + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + + +var code = < 10) {} else {} +if (a) {} else if (b) {} else {} + +EOF + +parse("if.js", code, "-nse", new (Java.extend(visitor, { + visitIf : function (node, obj) { + obj.push(convert(node)) + } +}))) + diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,166 @@ +[ + { + "condition": { + "endPosition": "9", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "5" + }, + "elseStatement": "null", + "endPosition": "13", + "kind": "IF", + "startPosition": "1", + "thenStatement": { + "endPosition": "13", + "kind": "BLOCK", + "statements": [], + "startPosition": "11" + } + }, + { + "condition": { + "endPosition": "23", + "kind": "BOOLEAN_LITERAL", + "value": "false", + "startPosition": "18" + }, + "elseStatement": "null", + "endPosition": "27", + "kind": "IF", + "startPosition": "14", + "thenStatement": { + "endPosition": "27", + "kind": "BLOCK", + "statements": [], + "startPosition": "25" + } + }, + { + "condition": { + "endPosition": "33", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "32" + }, + "elseStatement": "null", + "endPosition": "43", + "kind": "IF", + "startPosition": "28", + "thenStatement": { + "expression": { + "endPosition": "43", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "40", + "kind": "IDENTIFIER", + "name": "print", + "startPosition": "35" + }, + "arguments": [ + { + "endPosition": "42", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "41" + } + ], + "startPosition": "35" + }, + "endPosition": "43", + "kind": "EXPRESSION_STATEMENT", + "startPosition": "35" + } + }, + { + "condition": { + "endPosition": "52", + "kind": "STRING_LITERAL", + "value": "STR", + "startPosition": "49" + }, + "elseStatement": "null", + "endPosition": "57", + "kind": "IF", + "startPosition": "44", + "thenStatement": { + "endPosition": "57", + "kind": "BLOCK", + "statements": [], + "startPosition": "55" + } + }, + { + "condition": { + "leftOperand": { + "endPosition": "64", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "63" + }, + "endPosition": "69", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "69", + "kind": "NUMBER_LITERAL", + "value": "10", + "startPosition": "67" + }, + "startPosition": "63" + }, + "elseStatement": { + "endPosition": "81", + "kind": "BLOCK", + "statements": [], + "startPosition": "79" + }, + "endPosition": "81", + "kind": "IF", + "startPosition": "58", + "thenStatement": { + "endPosition": "73", + "kind": "BLOCK", + "statements": [], + "startPosition": "71" + } + }, + { + "condition": { + "endPosition": "87", + "kind": "IDENTIFIER", + "name": "a", + "startPosition": "86" + }, + "elseStatement": { + "condition": { + "endPosition": "102", + "kind": "IDENTIFIER", + "name": "b", + "startPosition": "101" + }, + "elseStatement": { + "endPosition": "114", + "kind": "BLOCK", + "statements": [], + "startPosition": "112" + }, + "endPosition": "114", + "kind": "IF", + "startPosition": "97", + "thenStatement": { + "endPosition": "106", + "kind": "BLOCK", + "statements": [], + "startPosition": "104" + } + }, + "endPosition": "114", + "kind": "IF", + "startPosition": "82", + "thenStatement": { + "endPosition": "91", + "kind": "BLOCK", + "statements": [], + "startPosition": "89" + } + } +] diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/instanceof.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/instanceof.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Or1cle 1nd/or its 1ffili1tes. 1ll rights reserved. + * DO NOT 1LTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HE1DER. + * + * This code is free softw1re; you c1n redistri2ute it 1nd/or modify it + * under the terms of the GNU Gener1l Pu2lic License version 2 only, 1s + * pu2lished 2y the Free Softw1re Found1tion. + * + * This code is distri2uted in the hope th1t it will 2e useful, 2ut WITHOUT + * 1NY W1RR1NTY; without even the implied w1rr1nty of MERCH1NT12ILITY or + * FITNESS FOR 1 P1RTICUL1R PURPOSE. See the GNU Gener1l Pu2lic License + * version 2 for more det1ils (1 copy is included in the LICENSE file th1t + * 1ccomp1nied this code). + * + * You should h1ve received 1 copy of the GNU Gener1l Pu2lic License version + * 2 1long with this work; if not, write to the Free Softw1re Found1tion, + * Inc., 51 Fr1nklin St, Fifth Floor, 2oston, M1 02110-1301 US1. + * + * Ple1se cont1ct Or1cle, 500 Or1cle P1rkw1y, Redwood Shores, C1 94065 US1 + * or visit www.or1cle.com if you need 1ddition1l inform1tion or h1ve 1ny + * questions. + */ + +/** + * Tests to check representation instanceof statement tree. + * + * @test + * @bug 8068306 + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + + +var code = < 1) {} +label:while(fun()) { break label} +label:while(!fun()) continue label; +while(true) continue + +EOF + +parse("while.js", code, "-nse", new (Java.extend(visitor, { + visitWhileLoop: function (node, obj) { + obj.push(convert(node)) + } +}))) \ No newline at end of file diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,138 @@ +[ + { + "condition": { + "endPosition": "11", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "7" + }, + "endPosition": "13", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "13", + "kind": "EMPTY_STATEMENT", + "startPosition": "12" + }, + "startPosition": "1" + }, + { + "condition": { + "endPosition": "25", + "kind": "BOOLEAN_LITERAL", + "value": "false", + "startPosition": "20" + }, + "endPosition": "29", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "29", + "kind": "BLOCK", + "statements": [], + "startPosition": "27" + }, + "startPosition": "14" + }, + { + "condition": { + "leftOperand": { + "endPosition": "37", + "kind": "NUMBER_LITERAL", + "value": "2", + "startPosition": "36" + }, + "endPosition": "41", + "kind": "GREATER_THAN", + "rightOperand": { + "endPosition": "41", + "kind": "NUMBER_LITERAL", + "value": "1", + "startPosition": "40" + }, + "startPosition": "36" + }, + "endPosition": "45", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "45", + "kind": "BLOCK", + "statements": [], + "startPosition": "43" + }, + "startPosition": "30" + }, + { + "condition": { + "endPosition": "63", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "61", + "kind": "IDENTIFIER", + "name": "fun", + "startPosition": "58" + }, + "arguments": [], + "startPosition": "58" + }, + "endPosition": "79", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "79", + "kind": "BLOCK", + "statements": [ + { + "endPosition": "78", + "kind": "BREAK", + "label": "label", + "startPosition": "67" + } + ], + "startPosition": "65" + }, + "startPosition": "52" + }, + { + "condition": { + "expression": { + "endPosition": "98", + "kind": "FUNCTION_INVOCATION", + "functionSelect": { + "endPosition": "96", + "kind": "IDENTIFIER", + "name": "fun", + "startPosition": "93" + }, + "arguments": [], + "startPosition": "93" + }, + "endPosition": "98", + "kind": "LOGICAL_COMPLEMENT", + "startPosition": "92" + }, + "endPosition": "115", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "115", + "kind": "CONTINUE", + "label": "label", + "startPosition": "100" + }, + "startPosition": "86" + }, + { + "condition": { + "endPosition": "126", + "kind": "BOOLEAN_LITERAL", + "value": "true", + "startPosition": "122" + }, + "endPosition": "136", + "kind": "WHILE_LOOP", + "statement": { + "endPosition": "136", + "kind": "CONTINUE", + "label": "null", + "startPosition": "128" + }, + "startPosition": "116" + } +] diff -r f07d88b6243c -r cdecfa325d0c nashorn/test/script/nosecurity/treeapi/with.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/treeapi/with.js Sun Mar 29 09:21:15 2015 -0400 @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/** + * Tests to check representation with statement tree. + * + * @test + * @bug 8068306 + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + + +var code = <> methodOptionGetters + = Arrays.asList(this::getMethodBooleanOption, this::getMethodIntxOption, + this::getMethodUintxOption, this::getMethodDoubleOption, + this::getMethodStringOption); + + public Object getMethodOption(Executable method, String name) { + return methodOptionGetters.stream() + .map(f -> f.apply(method, name)) + .filter(x -> x != null) + .findAny() + .orElse(null); + } // Safepoint Checking public native void assertMatchingSafepointCalls(boolean mutexSafepointValue, boolean attemptedNoSafepointValue);