--- a/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -297,3 +297,4 @@
d6224d6021459ac8b3832e822f5acc849fa944af jdk9-b52
874d76e4699dfcd61ae1826c9fe0ddc1610ad598 jdk9-b53
82cd31c5d6ca8d4c1653f4eb1c09eb2d9a3b2813 jdk9-b54
+c97e2d1bad9708d379793ba2a4c848eda14c741e jdk9-b55
--- a/.hgtags-top-repo Fri Mar 20 11:42:31 2015 -0700
+++ b/.hgtags-top-repo Fri Mar 27 09:02:55 2015 +0100
@@ -297,3 +297,4 @@
1822e59f17121b09e7899cf338cfb6e37fe5fceb jdk9-b52
d6ed47125a76cd1cf8a100568507bfb5e9669d9f jdk9-b53
cb7367141e910e265b8344a8facee740bd1e5467 jdk9-b54
+0c37a832458f0e0b7d2a3f1a6f69aeae311aeb18 jdk9-b55
--- a/common/autoconf/configure.ac Fri Mar 20 11:42:31 2015 -0700
+++ b/common/autoconf/configure.ac Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/common/autoconf/flags.m4 Fri Mar 20 11:42:31 2015 -0700
+++ b/common/autoconf/flags.m4 Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/common/autoconf/generated-configure.sh Fri Mar 20 11:42:31 2015 -0700
+++ b/common/autoconf/generated-configure.sh Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/common/autoconf/toolchain.m4 Fri Mar 20 11:42:31 2015 -0700
+++ b/common/autoconf/toolchain.m4 Fri Mar 27 09:02:55 2015 +0100
@@ -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])
--- a/corba/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/corba/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -297,3 +297,4 @@
b8538bbb6f224ab1dabba579137099c166ad4724 jdk9-b52
aadc16ca5ab7d56f92ef9dbfa443595a939241b4 jdk9-b53
d469c5ad0c763e325a78e0af3016878a57dfc5cc jdk9-b54
+734ca5311a225711b79618f3e92f47f07c82154a jdk9-b55
--- a/hotspot/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -457,3 +457,4 @@
9fb7fdc554db5be5c5b10f88f529ec3b870c44e3 jdk9-b52
effd5ef0c3eb4bb85aa975c489d6761dbf13ad6a jdk9-b53
c3b117fa5bdedfafd9ed236403e6d406911195b1 jdk9-b54
+be49ab55e5c498c5077bbf58c2737100d1992339 jdk9-b55
--- a/hotspot/agent/src/os/linux/libproc.h Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/agent/src/os/linux/libproc.h Fri Mar 27 09:02:55 2015 +0100
@@ -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 <stdint.h>
#include "proc_service.h"
-#if defined(arm) || defined(ppc)
+#ifdef ALT_SASRCDIR
#include "libproc_md.h"
#endif
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Fri Mar 27 09:02:55 2015 +0100
@@ -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++;
+ }
}
}
--- a/hotspot/make/aix/makefiles/rules.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/aix/makefiles/rules.make Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/hotspot/make/bsd/makefiles/rules.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/bsd/makefiles/rules.make Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/hotspot/make/defs.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/defs.make Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/make/linux/makefiles/arm.make Fri Mar 20 11:42:31 2015 -0700
+++ /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
--- a/hotspot/make/linux/makefiles/buildtree.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/linux/makefiles/buildtree.make Fri Mar 27 09:02:55 2015 +0100
@@ -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)"; \
--- a/hotspot/make/linux/makefiles/defs.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/linux/makefiles/defs.make Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/make/linux/makefiles/gcc.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/linux/makefiles/gcc.make Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/make/linux/makefiles/ppc.make Fri Mar 20 11:42:31 2015 -0700
+++ /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
--- a/hotspot/make/linux/makefiles/rules.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/linux/makefiles/rules.make Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/hotspot/make/linux/makefiles/saproc.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/linux/makefiles/saproc.make Fri Mar 27 09:02:55 2015 +0100
@@ -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) \
--- a/hotspot/make/linux/makefiles/vm.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/linux/makefiles/vm.make Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/make/linux/platform_arm Fri Mar 20 11:42:31 2015 -0700
+++ /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
--- a/hotspot/make/linux/platform_ppc Fri Mar 20 11:42:31 2015 -0700
+++ /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
--- a/hotspot/make/solaris/makefiles/rules.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/solaris/makefiles/rules.make Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/hotspot/make/windows/makefiles/rules.make Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/make/windows/makefiles/rules.make Fri Mar 27 09:02:55 2015 +0100
@@ -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).
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -2776,7 +2776,6 @@
__ stop("unexpected profiling mismatch");
__ bind(ok);
- __ pop(tmp);
}
#endif
// first time here. Set profile type.
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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));
}
}
}
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<u1>::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<u1>::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<u1>::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<u1>::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<u1>::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 */
+
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Mar 20 11:42:31 2015 -0700
+++ /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<u1>::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<u1>::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<u1>::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<u1>::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<u1>::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 */
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Mar 20 11:42:31 2015 -0700
+++ /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<u1>::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<u1>::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<u1>::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<u1>::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<u1>::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
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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");
--- a/hotspot/src/os/solaris/vm/jvm_solaris.h Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os/solaris/vm/jvm_solaris.h Fri Mar 27 09:02:55 2015 +0100
@@ -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 <dirent.h> /* For DIR */
+#undef __USE_LEGACY_PROTOTYPES__
#include <sys/param.h> /* For MAXPATHLEN */
#include <sys/socket.h> /* For socklen_t */
#include <unistd.h> /* For F_OK, R_OK, W_OK */
--- a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<jbyte> (volatile jbyte* p) { register jbyte t = load(p); inlasm_acquire_reg(t); return t; }
+template<> inline jshort OrderAccess::specialized_load_acquire<jshort>(volatile jshort* p) { register jshort t = load(p); inlasm_acquire_reg(t); return t; }
+template<> inline jint OrderAccess::specialized_load_acquire<jint> (volatile jint* p) { register jint t = load(p); inlasm_acquire_reg(t); return t; }
+template<> inline jlong OrderAccess::specialized_load_acquire<jlong> (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
--- a/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<jbyte> (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<jshort>(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<jint> (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<jlong> (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<jfloat> (volatile jfloat* p, jfloat v) {
+ release_store_fence((volatile jint*)p, jint_cast(v));
+}
+template<>
+inline void OrderAccess::specialized_release_store_fence<jdouble>(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
--- a/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<jbyte> (volatile jbyte* p) { register jbyte t = load(p); inlasm_acquire_reg(t); return t; }
+template<> inline jshort OrderAccess::specialized_load_acquire<jshort>(volatile jshort* p) { register jshort t = load(p); inlasm_acquire_reg(t); return t; }
+template<> inline jint OrderAccess::specialized_load_acquire<jint> (volatile jint* p) { register jint t = load(p); inlasm_acquire_reg(t); return t; }
+template<> inline jlong OrderAccess::specialized_load_acquire<jlong> (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
--- a/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<jbyte> (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<jshort>(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<jint> (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<jlong> (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<jfloat> (volatile jfloat* p, jfloat v) {
+ release_store_fence((volatile jint*)p, jint_cast(v));
+}
+template<>
+inline void OrderAccess::specialized_release_store_fence<jdouble>(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
--- a/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il Fri Mar 27 09:02:55 2015 +0100
@@ -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.
--- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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 <intrin.h>
#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<X_ACQUIRE>::postfix() { }
+template<> inline void ScopedFence<RELEASE_X>::prefix() { }
+template<> inline void ScopedFence<RELEASE_X_FENCE>::prefix() { }
+template<> inline void ScopedFence<RELEASE_X_FENCE>::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<jbyte> (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<jshort>(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<jint> (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<jfloat>(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<jdouble>(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
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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); }
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
};
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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");
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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: "
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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() {
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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_
}
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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;
}
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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();
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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;
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<InCSetState>::clear(); }
+ void clear(const HeapRegion* hr) { return set_by_index(hr->hrm_index(), InCSetState::NotInCSet); }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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();
}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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),
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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 ||
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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() {
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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"
--- a/hotspot/src/share/vm/interpreter/interp_masm.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/interp_masm.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/memory/generation.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/memory/generation.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
};
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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) {
--- a/hotspot/src/share/vm/opto/ad.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/opto/ad.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/opto/chaitin.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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 ) {
--- a/hotspot/src/share/vm/opto/optoreg.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/opto/optoreg.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/prims/whitebox.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -1133,6 +1133,75 @@
VMThread::execute(&force_safepoint_op);
WB_END
+template <typename T>
+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<bool> (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 <intx> (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 <uintx> (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 <double> (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 <ccstr> (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
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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) }
};
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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") \
\
--- a/hotspot/src/share/vm/runtime/orderAccess.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/runtime/orderAccess.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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 <store> <store> lwsync
+// <store>
+//
+// release_store_fence xchg <store> lwsync
+// membar #StoreLoad <store>
+// 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,<dummy>
-// #StoreStore
-// st %g0,[]
-//
-// acquire ld [%sp],%g0 ld.acq <r>=[sp] movl (sp),<r>
-// membar #LoadLoad |
-// #LoadStore
-//
-// release_store membar #LoadStore | st.rel <store>
-// #StoreStore
-// st
+// load_acquire <load> <load> <load>
+// lwsync
//
-// store_fence st st lock xchg
-// fence mf
-//
-// load_acquire ld ld.acq <load>
-// 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 <ScopedFenceType T>
+class ScopedFenceGeneral: public StackObj {
+ public:
+ void prefix() {}
+ void postfix() {}
+};
+
+template <ScopedFenceType T>
+class ScopedFence : public ScopedFenceGeneral<T> {
+ void *const _field;
+ public:
+ ScopedFence(void *const field) : _field(field) { prefix(); }
+ ~ScopedFence() { postfix(); }
+ void prefix() { ScopedFenceGeneral<T>::prefix(); }
+ void postfix() { ScopedFenceGeneral<T>::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<typename T> static T specialized_load_acquire (volatile T* p );
+ template<typename T> static void specialized_release_store (volatile T* p, T v);
+ template<typename T> static void specialized_release_store_fence(volatile T* p, T v);
+
+ template<typename FieldType, ScopedFenceType FenceType>
+ static void ordered_store(volatile FieldType* p, FieldType v);
+
+ template<typename FieldType, ScopedFenceType FenceType>
+ 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
--- a/hotspot/src/share/vm/runtime/orderAccess.inline.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/runtime/orderAccess.inline.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<X_ACQUIRE>::postfix() { OrderAccess::acquire(); }
+template<> inline void ScopedFenceGeneral<RELEASE_X>::prefix() { OrderAccess::release(); }
+template<> inline void ScopedFenceGeneral<RELEASE_X_FENCE>::prefix() { OrderAccess::release(); }
+template<> inline void ScopedFenceGeneral<RELEASE_X_FENCE>::postfix() { OrderAccess::fence(); }
+
+
+template <typename FieldType, ScopedFenceType FenceType>
+inline void OrderAccess::ordered_store(volatile FieldType* p, FieldType v) {
+ ScopedFence<FenceType> f((void*)p);
+ store(p, v);
+}
+
+template <typename FieldType, ScopedFenceType FenceType>
+inline FieldType OrderAccess::ordered_load(volatile FieldType* p) {
+ ScopedFence<FenceType> 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<typename T> inline T OrderAccess::specialized_load_acquire (volatile T* p) { return ordered_load<T, X_ACQUIRE>(p); }
+template<typename T> inline void OrderAccess::specialized_release_store (volatile T* p, T v) { ordered_store<T, RELEASE_X>(p, v); }
+template<typename T> inline void OrderAccess::specialized_release_store_fence(volatile T* p, T v) { ordered_store<T, RELEASE_X_FENCE>(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
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/hotspot/src/share/vm/runtime/vm_version.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/services/mallocSiteTable.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/services/mallocSiteTable.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/hotspot/src/share/vm/services/mallocSiteTable.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
--- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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 <ctype.h>
+#define __USE_LEGACY_PROTOTYPES__
# include <dirent.h>
+#undef __USE_LEGACY_PROTOTYPES__
# include <string.h>
# include <strings.h> // for bsd'isms
# include <stdarg.h>
--- a/hotspot/src/share/vm/utilities/macros.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/utilities/macros.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/hotspot/src/share/vm/utilities/nativeCallStack.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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<NativeCallStack*>(this);
- p->_hash_value = (int)(hash_val & 0xFFFFFFFF);
+ p->_hash_value = (unsigned int)(hash_val & 0xFFFFFFFF);
}
return _hash_value;
}
--- a/hotspot/src/share/vm/utilities/nativeCallStack.hpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/utilities/nativeCallStack.hpp Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/hotspot/src/share/vm/utilities/workgroup.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/oracle/GetMethodOptionTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<Executable, String, Object> 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<Executable, String, Object> getter;
+ private TestCase(Object value, BiFunction<Executable, String, Object> 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;
+ }
+}
--- a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Fri Mar 20 11:42:31 2015 -0700
+++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Fri Mar 27 09:02:55 2015 +0100
@@ -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 {
--- a/jaxp/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/jaxp/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -297,3 +297,4 @@
57b26c883d54f45912bc3885ccad3c6b80960b1f jdk9-b52
d5b5a010a16688f188f5a9247ed873f5100b530c jdk9-b53
542c0c855ad467624cbedf11bff08e44b86b068d jdk9-b54
+2a460ce60ed47081f756f0cc0321d8e9ba7cac17 jdk9-b55
--- a/jaxws/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/jaxws/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -300,3 +300,4 @@
1d1e7704eca9c77ebe6a8705d17ac568801f7a3b jdk9-b52
b8fbe40efa97fe0753076ccc6dfc50747c7877d0 jdk9-b53
83a0cf0e08788c33872e1fe3e87bf9a0d1e59eaa jdk9-b54
+ca481b0492c82cc38fa0e6b746305ed88c26b4fd jdk9-b55
--- a/jdk/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -297,3 +297,4 @@
607ea68032cd4a4cf2c7a7a41fcb39602d6a75e2 jdk9-b52
6cb5f5c34009630749a40cefe116d143f0b2583e jdk9-b53
568a62ab7d764d7c74ac1d87387dbe500662b551 jdk9-b54
+d49e247dade61f29f771f09b2105857492241156 jdk9-b55
--- a/jdk/make/Makefile Fri Mar 20 11:42:31 2015 -0700
+++ /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)
--- a/jdk/make/launcher/Launcher-jdk.pack200.gmk Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk Fri Mar 27 09:02:55 2015 +0100
@@ -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) \
--- a/jdk/make/lib/Lib-jdk.pack200.gmk Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/make/lib/Lib-jdk.pack200.gmk Fri Mar 27 09:02:55 2015 +0100
@@ -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), \
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -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]
--- a/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamException.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Fri Mar 27 09:02:55 2015 +0100
@@ -82,7 +82,7 @@
* <li><a name="redirect-output">a destination for <i>standard output</i>
* and <i>standard error</i></a>. 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 @@
* <li>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
*
* <li>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
*
* </ul>
--- a/jdk/src/java.base/share/classes/java/net/ProtocolException.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/ProtocolException.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
/**
--- a/jdk/src/java.base/share/classes/java/net/UnknownHostException.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/UnknownHostException.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/Date.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Date.java Fri Mar 27 09:02:55 2015 +0100
@@ -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();
}
--- a/jdk/src/java.base/share/classes/java/util/Optional.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Optional.java Fri Mar 27 09:02:55 2015 +0100
@@ -346,7 +346,7 @@
* </ul>
*
* @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
--- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Fri Mar 27 09:02:55 2015 +0100
@@ -244,7 +244,7 @@
* </ul>
*
* @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
--- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java Fri Mar 27 09:02:55 2015 +0100
@@ -244,7 +244,7 @@
* </ul>
*
* @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
--- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java Fri Mar 27 09:02:55 2015 +0100
@@ -244,7 +244,7 @@
* </ul>
*
* @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
--- a/jdk/src/java.base/share/classes/java/util/Properties.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Properties.java Fri Mar 27 09:02:55 2015 +0100
@@ -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 {
--- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
--- a/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java Fri Mar 27 09:02:55 2015 +0100
@@ -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;
+ }
};
}
--- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java Fri Mar 27 09:02:55 2015 +0100
@@ -631,6 +631,10 @@
/**
* Atomically updates Java variable to {@code x} if it is currently
* holding {@code expected}.
+ *
+ * <p>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}.
+ *
+ * <p>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}.
+ *
+ * <p>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,
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java Fri Mar 27 09:02:55 2015 +0100
@@ -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.
*/
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Fri Mar 27 09:02:55 2015 +0100
@@ -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.
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -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.
*/
--- a/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Fri Mar 27 09:02:55 2015 +0100
@@ -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-----");
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java Fri Mar 27 09:02:55 2015 +0100
@@ -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));
}
}
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/Pem.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
+ }
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -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) {
--- a/jdk/src/java.base/share/native/libjli/manifest_info.h Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/native/libjli/manifest_info.h Fri Mar 27 09:02:55 2015 +0100
@@ -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 */
--- a/jdk/src/java.base/share/native/libjli/parse_manifest.c Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/share/native/libjli/parse_manifest.c Fri Mar 27 09:02:55 2015 +0100
@@ -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;
}
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -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));
--- a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h Fri Mar 27 09:02:55 2015 +0100
@@ -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:
--- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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*)"<empty>";
+ return "<empty>";
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) {
--- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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) {
--- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.h Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.h Fri Mar 27 09:02:55 2015 +0100
@@ -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,
--- a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/jdk/src/jdk.pack200/share/native/unpack200/main.cpp Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.pack200/share/native/unpack200/main.cpp Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipConstants.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/test/TEST.ROOT Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/TEST.ROOT Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/test/TEST.groups Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/TEST.groups Fri Mar 27 09:02:55 2015 +0100
@@ -38,7 +38,9 @@
:jdk_time \
:jdk_security \
:jdk_text \
- :core_tools
+ :core_tools \
+ :jdk_other \
+ :jdk_svc
###############################################################################
#
--- a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -26,6 +26,7 @@
* @run main/othervm LdapTimeoutTest
* @bug 7094377 8000487 6176036 7056489
* @summary Timeout tests for ldap
+ * @key intermittent
*/
import java.net.Socket;
--- a/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<String> childArgs = new ArrayList<String>(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<String> childArgs = new ArrayList<String>(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)
//----------------------------------------------------------------
--- a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<Class<?>> ARGS_CLASSES;
--- a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java Fri Mar 27 09:02:55 2015 +0100
@@ -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.*;
--- a/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/net/Inet6Address/serialize/Inet6AddressSerializationTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -42,6 +42,7 @@
* @test
* @bug 8007373
* @summary jdk7 backward compatibility serialization problem
+ * @key intermittent
*/
public class Inet6AddressSerializationTest {
--- a/jdk/test/java/net/SocketPermission/SocketPermissionTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/net/SocketPermission/SocketPermissionTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/jdk/test/java/nio/Buffer/genBasic.sh Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/nio/Buffer/genBasic.sh Fri Mar 27 09:02:55 2015 +0100
@@ -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-X.java.template >Basic$2.java
--- a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Fri Mar 27 09:02:55 2015 +0100
@@ -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=$3<CopyDirect-X-Memory.java.template >CopyDirect$2Memory.java
--- a/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java Fri Mar 27 09:02:55 2015 +0100
@@ -23,6 +23,7 @@
/* @test
* @summary Unit test for server-socket-channel adaptors
+ * @key intermittent
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh Fri Mar 27 09:02:55 2015 +0100
@@ -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`
--- a/jdk/test/java/nio/file/FileStore/Basic.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/nio/file/FileStore/Basic.java Fri Mar 27 09:02:55 2015 +0100
@@ -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.*;
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Fri Mar 27 09:02:55 2015 +0100
@@ -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.*;
--- a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java Fri Mar 27 09:02:55 2015 +0100
@@ -38,6 +38,7 @@
* @library ../../testlibrary
* @build TestLibrary ReferenceRegistryStub
* @run main/othervm InterfaceHash
+ * @key intermittent
*/
import java.lang.reflect.Constructor;
--- a/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java Fri Mar 27 09:02:55 2015 +0100
@@ -31,6 +31,7 @@
* @summary GC'ing objects whilst being exported to RMI should not cause exceptions
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
* @run main/othervm GcDuringExport
+ * @key intermittent
*/
import java.rmi.Remote;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<String> 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);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/test/java/util/Arrays/TimSortStackSize2.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/util/Arrays/TimSortStackSize2.java Fri Mar 27 09:02:55 2015 +0100
@@ -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) ->
--- a/jdk/test/java/util/Properties/Basic.java Fri Mar 20 11:42:31 2015 -0700
+++ /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!");
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Properties/LoadAndStoreNPE.java Fri Mar 27 09:02:55 2015 +0100
@@ -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!");
+ }
+ }
+}
--- a/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
}
}
}
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<Integer>", dataProviderClass = StreamTestDataProvider.class)
public void testDistinctDistinct(String name, TestData.OfRef<Integer> data) {
Collection<Integer> result = withData(data)
- .stream(s -> s.distinct().distinct(), new CollectorOps.TestParallelSizedOp<>())
+ .stream(s -> s.distinct().distinct())
.exercise();
assertUnique(result);
}
--- a/jdk/test/java/util/zip/EntryCount64k.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/java/util/zip/EntryCount64k.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<? extends ZipEntry> 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");
}
}
--- a/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java Fri Mar 27 09:02:55 2015 +0100
@@ -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());
--- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
*
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/Subject/doAs/NestedActions.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<String> cmds = new ArrayList<>();
+ cmds.add(JAVA);
+ StringBuilder sb = new StringBuilder();
+ cmds.add("-classpath");
+ for (int i=2; i<args.length; i++) {
+ sb.append(args[i]).append(PS);
+ }
+ cmds.add(sb.toString());
+ if (JAVA_OPTS != null && !JAVA_OPTS.isEmpty()) {
+ cmds.add(JAVA_OPTS);
+ }
+ cmds.add("-Djava.security.manager");
+ cmds.add("-Djava.security.policy=" + TEST_SOURCES + FS + args[1]);
+ cmds.add(args[0]);
+ try {
+ ProcessTools.executeCommand(cmds.toArray(new String[cmds.size()]))
+ .shouldHaveExitValue(0);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
+
+/**
+ * Test for nested Subject.doAs() invocation:
+ *
+ * WriteToFileAction (CN=Duke principal) ->
+ * ReadFromFileAction (CN=Duke principal) ->
+ * ReadPropertyAction (CN=Duke principal)
+ *
+ * The test expects AccessControllException.
+ */
+class NestedActionsACE {
+
+ public static void main(String args[]) {
+ Subject subject = new Subject();
+ subject.getPrincipals().add(new X500Principal("CN=Duke"));
+ WriteToFileNegativeAction writeToFile
+ = new WriteToFileNegativeAction(NestedActions.file);
+ Subject.doAs(subject, writeToFile);
+ }
+}
+
+/**
+ * Test for nested Subject.doAs() invocation:
+ *
+ * WriteToFileAction (CN=Duke principal) ->
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.pae Fri Mar 27 09:02:55 2015 +0100
@@ -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";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java Fri Mar 27 09:02:55 2015 +0100
@@ -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]);
}
--- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/X509Factory/BadPem.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<cert.length; i += 48) {
+ int blockLen = (cert.length > 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
+ }
+ }
+}
+
--- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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");
--- a/jdk/test/sun/text/resources/LocaleData Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/text/resources/LocaleData Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/jdk/test/sun/text/resources/LocaleDataTest.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
*
*/
--- a/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java Fri Mar 20 11:42:31 2015 -0700
+++ b/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- a/langtools/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -297,3 +297,4 @@
ee20efe0255d7ac6e06e88e06f7c72f6c6da7bf9 jdk9-b52
99ff00581f3633c1787bec21f2a8f3a2ffe57665 jdk9-b53
ed34864f3b43a7df394fce6c3f0bc86b70a5d686 jdk9-b54
+32a2e724988499e6f68611a65168c5f2fde0f6b9 jdk9-b55
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<S> extends Types.MapVisitor<S> implements Function<Type, Type> {
+
+ @Override
+ public Type apply(Type type) {
+ return visit(type);
+ }
+
+ List<Type> visit(List<Type> 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<Type> typarams = t.getTypeArguments();
+ List<Type> 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<Type> argtypes = t.argtypes;
+ Type restype = t.restype;
+ List<Type> thrown = t.thrown;
+ List<Type> argtypes1 = visit(argtypes, s);
+ Type restype1 = visit(restype, s);
+ List<Type> 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 <Z> Type map(TypeMapping<Z> 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<Type> map(List<Type> ts, Mapping f) {
- if (ts.nonEmpty()) {
- List<Type> 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 <Z> Type map(TypeMapping<Z> 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<Type> typarams = getTypeArguments();
- List<Type> 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<Type> argtypes1 = map(argtypes, f);
- Type restype1 = f.apply(restype);
- List<Type> 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<Type> 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<Void> toTypeVarMap = new TypeMapping<Void>() {
@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; }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Mar 27 09:02:55 2015 +0100
@@ -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 @@
// <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
public List<Type> cvarLowerBounds(List<Type> ts) {
- return map(ts, cvarLowerBoundMapping);
+ return ts.map(cvarLowerBoundMapping);
}
- private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") {
- public Type apply(Type t) {
+ private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() {
+ @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<Void> elemTypeFun = new TypeMapping<Void>() {
+ @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<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
+ private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() {
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<Type> erasure(List<Type> ts) {
- return Type.map(ts, erasureFun);
+ return erasure.visit(ts, false);
}
public Type erasureRecursive(Type t) {
@@ -2247,7 +2243,7 @@
}
public List<Type> erasureRecursive(List<Type> ts) {
- return Type.map(ts, erasureRecFun);
+ return erasure.visit(ts, true);
}
// </editor-fold>
@@ -3177,15 +3173,18 @@
* changing all recursive bounds from old to new list.
*/
public List<Type> newInstances(List<Type> tvars) {
- List<Type> tvars1 = Type.map(tvars, newInstanceFun);
+ List<Type> tvars1 = tvars.map(newInstanceFun);
for (List<Type> 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<Void> newInstanceFun = new TypeMapping<Void>() {
+ @Override
+ public TypeVar visitTypeVar(TypeVar t, Void _unused) {
+ return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata());
+ }
};
// </editor-fold>
@@ -3409,41 +3408,86 @@
}
/**
+ * Collect types into a new closure (using a @code{ClosureHolder})
+ */
+ public Collector<Type, ClosureHolder, List<Type>> closureCollector(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
+ return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip),
+ ClosureHolder::add,
+ ClosureHolder::merge,
+ ClosureHolder::closure);
+ }
+ //where
+ class ClosureHolder {
+ List<Type> closure;
+ final boolean minClosure;
+ final BiPredicate<Type, Type> shouldSkip;
+
+ ClosureHolder(boolean minClosure, BiPredicate<Type, Type> 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<Type> closure() {
+ return minClosure ? closureMin(closure) : closure;
+ }
+ }
+
+ BiPredicate<Type, Type> basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym;
+
+ /**
* Insert a type in a closure
*/
- public List<Type> insert(List<Type> cl, Type t) {
+ public List<Type> insert(List<Type> cl, Type t, BiPredicate<Type, Type> 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<Type> insert(List<Type> cl, Type t) {
+ return insert(cl, t, basicClosureSkip);
+ }
+
/**
* Form the union of two closures
*/
- public List<Type> union(List<Type> cl1, List<Type> cl2) {
+ public List<Type> union(List<Type> cl1, List<Type> cl2, BiPredicate<Type, Type> 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<Type> union(List<Type> cl1, List<Type> cl2) {
+ return union(cl1, cl2, basicClosureSkip);
+ }
+
/**
* Intersect two closures
*/
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<Type> argtypes2 = Type.map(argtypes,
+ List<Type> 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);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<AttrMode, String> 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<Void> {
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);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step));
+ List<Type> paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step));
List<Type> 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<Type> boundList = uv.getBounds(InferenceBound.UPPER);
+ List<Type> boundList = uv.getBounds(InferenceBound.UPPER).stream()
+ .collect(infer.types.closureCollector(true, infer.types::isSameType));
List<Type> boundListTail = boundList.tail;
while (boundList.nonEmpty()) {
List<Type> tmpTail = boundListTail;
@@ -2046,23 +2055,19 @@
List<FreeTypeListener> freetypeListeners = List.nil();
public InferenceContext(List<Type> 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<Void> fromTypeVarFun = new TypeMapping<Void>() {
+ @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);
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Mar 27 09:02:55 2015 +0100
@@ -232,8 +232,7 @@
}
}
String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
- List<Type> argtypes2 = Type.map(argtypes,
- deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
+ List<Type> 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<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
- return Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
+ return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Mar 27 09:02:55 2015 +0100
@@ -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;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Mar 27 09:02:55 2015 +0100
@@ -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}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Fri Mar 27 09:02:55 2015 +0100
@@ -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 <Z> List<Z> map(Function<A, Z> mapper) {
+ if (nonEmpty()) {
+ List<Z> tail1 = tail.map(mapper);
+ Z head1 = mapper.apply(head);
+ if (tail1 != tail || head1 != head)
+ return tail1.prepend(head1);
+ }
+ return (List<Z>)this;
+ }
+
+ @SuppressWarnings("unchecked")
public static <T> List<T> convert(Class<T> klass, List<?> list) {
if (list == null)
return null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8071847/T8071847.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<CA.length ; i+=2) {
+ char c1 = CA[i], c2=CA[i+1];
+ byteArry[bi++] = (byte)((Character.digit((int)c1,16)<<4) +
+ Character.digit((int)c2,16));
+ }
+ return byteArry;
+ }
+
+ File writeHexFile(String classFileName, String hexString) throws IOException {
+ File f = new File(classFileName);
+ FileOutputStream output = new FileOutputStream(f);
+ output.write(hexToByte(hexString));
+ output.close();
+ return f;
+ }
+
+ String javac(String className) {
+ StringWriter sw = new StringWriter();
+ PrintWriter out = new PrintWriter(sw);
+ int rc = 0;
+ List<String> 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();
+ }
+}
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Mar 20 11:42:31 2015 -0700
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/expression/BinopVoidTest.java Fri Mar 27 09:02:55 2015 +0100
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/expression/BinopVoidTest.out Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8048838/T8048838.java Fri Mar 27 09:02:55 2015 +0100
@@ -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 extends T2, T2 extends T3, T3 extends T4, T4 extends T5, T5 extends T6, T6 extends T7,
+ T7 extends T8, T8 extends T9, T9 extends T10, T10 extends T11, T11 extends T12,
+ T12 extends T13, T13 extends T14, T14 extends T15, T15 extends T16, T16 extends T17,
+ T17 extends T18, T18 extends T19, T19 extends T20, T20 extends T21, T21 extends T22,
+ T22 extends T23, T23 extends T24, T24 extends T25, T25 extends T26, T26 extends T27,
+ T27 extends T28, T28 extends T29, T29 extends T30, T30 extends T31, T31 extends T32,
+ T32 extends T33, T33 extends T34, T34 extends T35, T35 extends T36, T36 extends T37,
+ T37 extends T38, T38 extends T39, T39 extends T40, T40 extends T41, T41 extends T42,
+ T42 extends T43, T43 extends T44, T44 extends T45, T45 extends T46, T46 extends T47,
+ T47 extends T48, T48 extends T49, T49 extends T50, T50 extends T51, T51 extends T52,
+ T52 extends T53, T53 extends T54, T54 extends T55, T55 extends T56, T56 extends T57,
+ T57 extends T58, T58 extends T59, T59 extends T60, T60 extends T61, T61 extends T62,
+ T62 extends T63, T63 extends T64, T64 extends T65, T65 extends T66, T66 extends T67,
+ T67 extends T68, T68 extends T69, T69 extends T70, T70 extends T71, T71 extends T72,
+ T72 extends T73, T73 extends T74, T74 extends T75, T75 extends T76, T76 extends T77,
+ T77 extends T78, T78 extends T79, T79 extends T80, T80 extends T81, T81 extends T82,
+ T82 extends T83, T83 extends T84, T84 extends T85, T85 extends T86, T86 extends T87,
+ T87 extends T88, T88 extends T89, T89 extends T90, T90 extends T91, T91 extends T92,
+ T92 extends T93, T93 extends T94, T94 extends T95, T95 extends T96, T96 extends T97,
+ T97 extends T98, T98 extends T99, T99 extends T100, T100 extends Integer>
+ 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
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<X> {
+ boolean m(X x);
+ }
+
+ interface Sub<X> extends Sup<String> {
+ 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<Integer> s1 = c -> true;
+ Sub<Integer> s2 = Boolean::new;
+ Sub<Integer> s3 = new Sub<Integer>() {
+ @Override
+ public boolean m(String o) { return true; }
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.out Fri Mar 27 09:02:55 2015 +0100
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<T> {
+ public final ThrowingConsumer<T> consumer;
+
+ public Invocation(final ThrowingConsumer<T> consumer) {
+ this.consumer = consumer;
+ }
+ }
+
+ @FunctionalInterface
+ public interface ThrowingConsumer<T> extends BiConsumer<T,Consumer<Throwable>> {
+ @Override
+ default void accept(final T elem, final Consumer<Throwable> errorHandler) {
+ try {
+ acceptThrows(elem);
+ } catch (final Throwable e) {
+ errorHandler.accept(e);
+ }
+ }
+
+ void acceptThrows(T elem) throws Throwable;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.out Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,2 @@
+T8074381b.java:14:16: compiler.err.cant.apply.symbol: kindname.constructor, Invocation, T8074381b.ThrowingConsumer, @383, kindname.class, T8074381b.Invocation<T>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: T8074381b.ThrowingConsumer))
+1 error
--- a/make/CompileJavaModules.gmk Fri Mar 20 11:42:31 2015 -0700
+++ b/make/CompileJavaModules.gmk Fri Mar 27 09:02:55 2015 +0100
@@ -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, \
--- a/make/Images.gmk Fri Mar 20 11:42:31 2015 -0700
+++ b/make/Images.gmk Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/make/common/JavaCompilation.gmk Fri Mar 20 11:42:31 2015 -0700
+++ b/make/common/JavaCompilation.gmk Fri Mar 27 09:02:55 2015 +0100
@@ -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' \
--- a/make/common/NativeCompilation.gmk Fri Mar 20 11:42:31 2015 -0700
+++ b/make/common/NativeCompilation.gmk Fri Mar 27 09:02:55 2015 +0100
@@ -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)
--- a/nashorn/.hgtags Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/.hgtags Fri Mar 27 09:02:55 2015 +0100
@@ -288,3 +288,4 @@
fada76c29db9c792ad7127e674ef5337e15d2225 jdk9-b52
6cd23482ca9bd0caa6bfa6bf9064251178083d17 jdk9-b53
26460b897225010a4c7664eaff7a71f1156cacb3 jdk9-b54
+b2b332e64b7b2e06e25bccae9c0c0b585a03b4b5 jdk9-b55
--- a/nashorn/samples/findwith.js Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/samples/findwith.js Fri Mar 27 09:02:55 2015 +0100
@@ -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");
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/prettyprinter.js Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTree.java Fri Mar 27 09:02:55 2015 +0100
@@ -44,6 +44,7 @@
*
* @return the condition expression
*/
+ @Override
ExpressionTree getCondition();
/**
@@ -51,5 +52,6 @@
*
* @return the statement
*/
+ @Override
StatementTree getStatement();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTree.java Fri Mar 27 09:02:55 2015 +0100
@@ -57,6 +57,7 @@
*
* @return the statement
*/
+ @Override
StatementTree getStatement();
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -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;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<? extends ExpressionTree> 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<? extends ExpressionTree> 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<? extends Statement> stats = block.getStatements();
+ curStat = new BlockTreeImpl(block,
+ translateStats(sortStats? getOrderedStatements(stats) : stats));
+ return false;
+ }
+
+ private List<? extends Statement> getOrderedStatements(final List<? extends Statement> stats) {
+ final List<? extends Statement> statList = new ArrayList<>(stats);
+ statList.sort(Comparator.comparingInt(Node::getSourceOrder));
+ return statList;
+ }
+
private List<? extends StatementTree> translateStats(final List<? extends Statement> 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);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java Fri Mar 27 09:02:55 2015 +0100
@@ -139,7 +139,7 @@
}
}
- private CompilationUnitTree translate(final FunctionNode node) {
+ private static CompilationUnitTree translate(final FunctionNode node) {
return new IRTranslator().translate(node);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTree.java Fri Mar 27 09:02:55 2015 +0100
@@ -43,6 +43,7 @@
*
* @return the condition expression
*/
+ @Override
ExpressionTree getCondition();
/**
@@ -50,5 +51,6 @@
*
* @return the statement contained
*/
+ @Override
StatementTree getStatement();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Fri Mar 27 09:02:55 2015 +0100
@@ -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 {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Fri Mar 27 09:02:55 2015 +0100
@@ -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();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArrayBuffer.java Fri Mar 27 09:02:55 2015 +0100
@@ -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]));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Fri Mar 27 09:02:55 2015 +0100
@@ -1066,6 +1066,10 @@
* @param isStatement True if a statement (not used in a FOR.)
*/
private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
+ return variableStatement(varType, isStatement, -1);
+ }
+
+ private List<VarNode> 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;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Fri Mar 27 09:02:55 2015 +0100
@@ -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<MethodHandle> 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) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Fri Mar 27 09:02:55 2015 +0100
@@ -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;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Fri Mar 27 09:02:55 2015 +0100
@@ -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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8075090.js Fri Mar 27 09:02:55 2015 +0100
@@ -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);
+ }
+})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8075207.js Fri Mar 27 09:02:55 2015 +0100
@@ -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", <<CODE
+
+var hello = 'hello';
+
+function print_hello() {
+ var x = 2;
+ print(hello);
+ function inner_func() {}
+ var y = function() {
+ var PI = Math.PI;
+ function inner2() {}
+ var E = Math.E;
+ }
+}
+
+var hello = "hello 2";
+
+CODE, print);
+
+var stats = ast.sourceElements;
+Assert.assertTrue(stats.get(0) instanceof VariableTree);
+Assert.assertTrue(stats.get(1) instanceof FunctionDeclarationTree);
+Assert.assertTrue(stats.get(2) instanceof VariableTree);
+
+var print_hello = stats.get(1);
+Assert.assertEquals(print_hello.name, "print_hello");
+var print_hello_stats = print_hello.body.statements;
+Assert.assertTrue(print_hello_stats.get(0) instanceof VariableTree);
+Assert.assertTrue(print_hello_stats.get(1) instanceof ExpressionStatementTree);
+Assert.assertTrue(print_hello_stats.get(2) instanceof FunctionDeclarationTree);
+Assert.assertTrue(print_hello_stats.get(3) instanceof VariableTree);
+
+var anonFunc = print_hello_stats.get(3).initializer;
+var anonFunc_stats = anonFunc.body.statements;
+Assert.assertTrue(anonFunc_stats.get(0) instanceof VariableTree);
+Assert.assertTrue(anonFunc_stats.get(1) instanceof FunctionDeclarationTree);
+Assert.assertTrue(anonFunc_stats.get(2) instanceof VariableTree);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8075448.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8075448: nashorn parser API returns init variable tree object of a for
+ * loop after for loop statement tree object
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+var Parser = Java.type("jdk.nashorn.api.tree.Parser");
+var ForLoopTree = Java.type("jdk.nashorn.api.tree.ForLoopTree");
+var VariableTree = Java.type("jdk.nashorn.api.tree.VariableTree");
+var parser = Parser.create();
+
+var code = <<EOF
+for (var i = 0; i < 10; i++)
+ print("hello");
+EOF;
+
+var ast = parser.parse("test.js", code, print);
+var stats = ast.sourceElements;
+
+Assert.assertTrue(stats[0] instanceof VariableTree);
+Assert.assertEquals(stats[0].name, "i");
+Assert.assertTrue(stats[1] instanceof ForLoopTree);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8075454.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8075454: Anonymous functions have internal names exposed via parser API
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+var Parser = Java.type("jdk.nashorn.api.tree.Parser");
+var parser = Parser.create();
+
+var ast = parser.parse("test.js", <<EOF
+
+function(x) {
+ return x*x
+}
+
+EOF, print);
+
+Assert.assertNull(ast.sourceElements[0].name);
--- a/nashorn/test/script/basic/typedarrays.js Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/test/script/basic/typedarrays.js Fri Mar 27 09:02:55 2015 +0100
@@ -28,6 +28,17 @@
* @run
*/
+//JDK-8066217, constructor for arraybuffer not behaving as per spec
+function checkLength(ab, l) {
+ if (ab.byteLength != l) {
+ throw "length error: " + ab.byteLength + " != " + l;
+ }
+}
+checkLength(new ArrayBuffer(), 0);
+checkLength(new ArrayBuffer(0), 0);
+checkLength(new ArrayBuffer(1024), 1024);
+checkLength(new ArrayBuffer(1,2,3), 1);
+checkLength(new ArrayBuffer([17]), 17);
var typeDefinitions = [
Int8Array,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/parser-args.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+ /**
+ * @bug 8068303
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "/../assert.js")
+
+var Parser = Java.type('jdk.nashorn.api.tree.Parser')
+
+
+var code = <<EOF
+ const a= 1;
+EOF
+
+try {
+ Parser.create().parse("const.js", code, null)
+ fail("Parser need to throw exception there")
+} catch (e) {}
+
+try {
+ Parser.create("--const-as-var").parse("const.js", code, null)
+} catch (e) {
+ fail("Parser failed with exception :" + e)
+}
+
+var code = <<EOF
+ try {
+ that()
+ } catch (e if e instanceof TypeError) {
+ handle()
+ } catch (e) {
+ rest()
+ }
+EOF
+
+try {
+ Parser.create("-nse").parse("const.js", code, null)
+ fail("Parser need to throw exception there")
+} catch (e) {
+}
+
+try {
+ Parser.create().parse("extension.js", code, null)
+} catch (e) {
+ fail("Parser failed with exception :" + e)
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/parser.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,92 @@
+/*
+ * 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 8068303
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "/../assert.js")
+
+var Parser = Java.type('jdk.nashorn.api.tree.Parser')
+var Nashorn = Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory')
+var File = java.io.File
+var Reader = java.io.FileReader
+
+
+var test_dir = __DIR__ + "/parsertests"
+var files = new File(test_dir).listFiles()
+
+// File source
+for (var i in files) {
+ var parser = Parser.create("-scripting", "--const-as-var", "-doe")
+ try {
+ var tree = parser.parse(files[i], null);
+ Assert.assertNotNull(tree);
+ }
+ catch (e) {
+ fail("Parser failed with message :" + e)
+ }
+}
+
+// Reader source
+for (var i in files) {
+ var parser = Parser.create("-scripting", "--const-as-var", "-doe")
+ try {
+ var tree = parser.parse(files[i].getName(), new Reader(files[i]), null)
+ Assert.assertNotNull(tree);
+ } catch (e) {
+ fail("Parser failed with message :" + e)
+ }
+
+}
+
+// URL source
+for (var i in files) {
+ var parser = Parser.create("-scripting", "--const-as-var", "-doe")
+ try {
+ var tree = parser.parse(files[i].toURI().toURL(), null)
+ Assert.assertNotNull(tree);
+ } catch (e) {
+ fail("Parser failed with message :" + e)
+ }
+}
+
+// ScriptObjectMirror
+
+for (var i in files) {
+ var parser = Parser.create("-scripting", "--const-as-var", "-doe")
+ var engine = new Nashorn().getScriptEngine("-scripting", "--const-as-var", "-doe")
+ try {
+ engine.compile(new Reader(files[i]))
+ var mirror = engine.createBindings()
+ mirror['name'] = mirror['script'] = files[i].getName()
+ var tree = parser.parse(mirror, null)
+ Assert.assertNotNull(tree);
+ } catch (e) {
+ fail("Parser failed with message :" + e)
+ }
+}
+
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Fri Mar 20 11:42:31 2015 -0700
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -1364,32 +1364,6 @@
]
},
{
- "endPosition": "1380",
- "kind": "FUNCTION",
- "name": "test",
- "body": {
- "endPosition": "1377",
- "kind": "BLOCK",
- "statements": [
- {
- "expression": {
- "endPosition": "1377",
- "kind": "STRING_LITERAL",
- "value": "use strict",
- "startPosition": "1367"
- },
- "endPosition": "1377",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "1367"
- }
- ],
- "startPosition": "1364"
- },
- "strict": "true",
- "startPosition": "1348",
- "parameters": []
- },
- {
"endPosition": "1282",
"kind": "VARIABLE",
"name": "hello",
@@ -1495,6 +1469,32 @@
"endPosition": "1347",
"kind": "EXPRESSION_STATEMENT",
"startPosition": "1333"
+ },
+ {
+ "endPosition": "1380",
+ "kind": "FUNCTION",
+ "name": "test",
+ "body": {
+ "endPosition": "1377",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "1377",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "1367"
+ },
+ "endPosition": "1377",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "1367"
+ }
+ ],
+ "startPosition": "1364"
+ },
+ "strict": "true",
+ "startPosition": "1348",
+ "parameters": []
}
],
"sourceName": "parsertests/functions.js",
@@ -3976,6 +3976,17 @@
"kind": "COMPILATION_UNIT",
"sourceElements": [
{
+ "expression": {
+ "endPosition": "1133",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "1123"
+ },
+ "endPosition": "1133",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "1123"
+ },
+ {
"endPosition": "1165",
"kind": "FUNCTION",
"name": "f",
@@ -4000,17 +4011,6 @@
"strict": "true",
"startPosition": "1136",
"parameters": []
- },
- {
- "expression": {
- "endPosition": "1133",
- "kind": "STRING_LITERAL",
- "value": "use strict",
- "startPosition": "1123"
- },
- "endPosition": "1133",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "1123"
}
],
"sourceName": "parsertests/useStrict.js",
@@ -4919,808 +4919,6 @@
"parameters": []
},
{
- "endPosition": "3598",
- "kind": "FUNCTION",
- "name": "processFiles",
- "body": {
- "endPosition": "3555",
- "kind": "BLOCK",
- "statements": [
- {
- "endPosition": "2938",
- "kind": "VARIABLE",
- "name": "File",
- "startPosition": "2906",
- "initializer": {
- "endPosition": "2938",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "type",
- "expression": {
- "endPosition": "2917",
- "kind": "IDENTIFIER",
- "name": "Java",
- "startPosition": "2913"
- },
- "endPosition": "2922",
- "kind": "MEMBER_SELECT",
- "startPosition": "2913"
- },
- "arguments": [
- {
- "endPosition": "2936",
- "kind": "STRING_LITERAL",
- "value": "java.io.File",
- "startPosition": "2924"
- }
- ],
- "startPosition": "2913"
- }
- },
- {
- "endPosition": "2993",
- "kind": "VARIABLE",
- "name": "files",
- "startPosition": "2947",
- "initializer": {
- "endPosition": "2993",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "listFiles",
- "expression": {
- "constructorExpression": {
- "endPosition": "2981",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "2963",
- "kind": "IDENTIFIER",
- "name": "File",
- "startPosition": "2959"
- },
- "arguments": [
- {
- "leftOperand": {
- "endPosition": "2971",
- "kind": "IDENTIFIER",
- "name": "__DIR__",
- "startPosition": "2964"
- },
- "endPosition": "2980",
- "kind": "PLUS",
- "rightOperand": {
- "endPosition": "2980",
- "kind": "IDENTIFIER",
- "name": "subdir",
- "startPosition": "2974"
- },
- "startPosition": "2964"
- }
- ],
- "startPosition": "2959"
- },
- "endPosition": "2981",
- "kind": "NEW",
- "startPosition": "2955"
- },
- "endPosition": "2991",
- "kind": "MEMBER_SELECT",
- "startPosition": "2955"
- },
- "arguments": [],
- "startPosition": "2955"
- }
- },
- {
- "expression": {
- "endPosition": "3026",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "sort",
- "expression": {
- "identifier": "Arrays",
- "expression": {
- "identifier": "util",
- "expression": {
- "endPosition": "3002",
- "kind": "IDENTIFIER",
- "name": "java",
- "startPosition": "2998"
- },
- "endPosition": "3007",
- "kind": "MEMBER_SELECT",
- "startPosition": "2998"
- },
- "endPosition": "3014",
- "kind": "MEMBER_SELECT",
- "startPosition": "2998"
- },
- "endPosition": "3019",
- "kind": "MEMBER_SELECT",
- "startPosition": "2998"
- },
- "arguments": [
- {
- "endPosition": "3025",
- "kind": "IDENTIFIER",
- "name": "files",
- "startPosition": "3020"
- }
- ],
- "startPosition": "2998"
- },
- "endPosition": "3026",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "2998"
- },
- {
- "endPosition": "3049",
- "kind": "VARIABLE",
- "name": "file",
- "startPosition": "3045"
- },
- {
- "expression": {
- "endPosition": "3058",
- "kind": "IDENTIFIER",
- "name": "files",
- "startPosition": "3053"
- },
- "endPosition": "3555",
- "kind": "FOR_IN_LOOP",
- "forEach": "true",
- "variable": {
- "endPosition": "3049",
- "kind": "IDENTIFIER",
- "name": "file",
- "startPosition": "3045"
- },
- "statement": {
- "endPosition": "3555",
- "kind": "BLOCK",
- "statements": [
- {
- "condition": {
- "endPosition": "3098",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "endsWith",
- "expression": {
- "identifier": "name",
- "expression": {
- "endPosition": "3077",
- "kind": "IDENTIFIER",
- "name": "file",
- "startPosition": "3073"
- },
- "endPosition": "3082",
- "kind": "MEMBER_SELECT",
- "startPosition": "3073"
- },
- "endPosition": "3091",
- "kind": "MEMBER_SELECT",
- "startPosition": "3073"
- },
- "arguments": [
- {
- "endPosition": "3096",
- "kind": "STRING_LITERAL",
- "value": ".js",
- "startPosition": "3093"
- }
- ],
- "startPosition": "3073"
- },
- "endPosition": "3550",
- "kind": "IF",
- "startPosition": "3069",
- "thenStatement": {
- "endPosition": "3550",
- "kind": "BLOCK",
- "statements": [
- {
- "endPosition": "3141",
- "kind": "VARIABLE",
- "name": "script",
- "startPosition": "3117",
- "initializer": {
- "endPosition": "3141",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3135",
- "kind": "IDENTIFIER",
- "name": "readFully",
- "startPosition": "3126"
- },
- "arguments": [
- {
- "endPosition": "3140",
- "kind": "IDENTIFIER",
- "name": "file",
- "startPosition": "3136"
- }
- ],
- "startPosition": "3126"
- }
- },
- {
- "endPosition": "3179",
- "kind": "VARIABLE",
- "name": "parser",
- "startPosition": "3158",
- "initializer": {
- "constructorExpression": {
- "endPosition": "3179",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3177",
- "kind": "IDENTIFIER",
- "name": "Parser",
- "startPosition": "3171"
- },
- "arguments": [],
- "startPosition": "3171"
- },
- "endPosition": "3179",
- "kind": "NEW",
- "startPosition": "3167"
- }
- },
- {
- "endPosition": "3415",
- "kind": "VARIABLE",
- "name": "tree",
- "startPosition": "3196",
- "initializer": {
- "endPosition": "3415",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "parse",
- "expression": {
- "endPosition": "3209",
- "kind": "IDENTIFIER",
- "name": "parser",
- "startPosition": "3203"
- },
- "endPosition": "3215",
- "kind": "MEMBER_SELECT",
- "startPosition": "3203"
- },
- "arguments": [
- {
- "leftOperand": {
- "leftOperand": {
- "endPosition": "3222",
- "kind": "IDENTIFIER",
- "name": "subdir",
- "startPosition": "3216"
- },
- "endPosition": "3227",
- "kind": "PLUS",
- "rightOperand": {
- "endPosition": "3227",
- "kind": "STRING_LITERAL",
- "value": "/",
- "startPosition": "3226"
- },
- "startPosition": "3216"
- },
- "endPosition": "3240",
- "kind": "PLUS",
- "rightOperand": {
- "identifier": "name",
- "expression": {
- "endPosition": "3235",
- "kind": "IDENTIFIER",
- "name": "file",
- "startPosition": "3231"
- },
- "endPosition": "3240",
- "kind": "MEMBER_SELECT",
- "startPosition": "3231"
- },
- "startPosition": "3216"
- },
- {
- "endPosition": "3248",
- "kind": "IDENTIFIER",
- "name": "script",
- "startPosition": "3242"
- },
- {
- "endPosition": "3286",
- "kind": "FUNCTION_EXPRESSION",
- "body": {
- "endPosition": "3397",
- "kind": "BLOCK",
- "statements": [
- {
- "expression": {
- "endPosition": "3365",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3312",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3307"
- },
- "arguments": [
- {
- "endPosition": "3364",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "stringify",
- "expression": {
- "endPosition": "3317",
- "kind": "IDENTIFIER",
- "name": "JSON",
- "startPosition": "3313"
- },
- "endPosition": "3327",
- "kind": "MEMBER_SELECT",
- "startPosition": "3313"
- },
- "arguments": [
- {
- "endPosition": "3354",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "convert",
- "expression": {
- "endPosition": "3334",
- "kind": "IDENTIFIER",
- "name": "parser",
- "startPosition": "3328"
- },
- "endPosition": "3342",
- "kind": "MEMBER_SELECT",
- "startPosition": "3328"
- },
- "arguments": [
- {
- "endPosition": "3353",
- "kind": "IDENTIFIER",
- "name": "diagnostic",
- "startPosition": "3343"
- }
- ],
- "startPosition": "3328"
- },
- {
- "endPosition": "3360",
- "kind": "NULL_LITERAL",
- "startPosition": "3356"
- },
- {
- "endPosition": "3363",
- "kind": "NUMBER_LITERAL",
- "value": "2",
- "startPosition": "3362"
- }
- ],
- "startPosition": "3313"
- }
- ],
- "startPosition": "3307"
- },
- "endPosition": "3365",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3307"
- },
- {
- "expression": {
- "endPosition": "3396",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3391",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3386"
- },
- "arguments": [
- {
- "endPosition": "3394",
- "kind": "STRING_LITERAL",
- "value": ",",
- "startPosition": "3393"
- }
- ],
- "startPosition": "3386"
- },
- "endPosition": "3396",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3386"
- }
- ],
- "startPosition": "3286"
- },
- "strict": "false",
- "startPosition": "3286",
- "parameters": [
- {
- "endPosition": "3284",
- "kind": "IDENTIFIER",
- "name": "diagnostic",
- "startPosition": "3274"
- }
- ]
- }
- ],
- "startPosition": "3203"
- }
- },
- {
- "condition": {
- "leftOperand": {
- "endPosition": "3437",
- "kind": "IDENTIFIER",
- "name": "tree",
- "startPosition": "3433"
- },
- "endPosition": "3445",
- "kind": "NOT_EQUAL_TO",
- "rightOperand": {
- "endPosition": "3445",
- "kind": "NULL_LITERAL",
- "startPosition": "3441"
- },
- "startPosition": "3433"
- },
- "endPosition": "3541",
- "kind": "IF",
- "startPosition": "3429",
- "thenStatement": {
- "endPosition": "3541",
- "kind": "BLOCK",
- "statements": [
- {
- "expression": {
- "endPosition": "3500",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3469",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3464"
- },
- "arguments": [
- {
- "endPosition": "3499",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "stringify",
- "expression": {
- "endPosition": "3474",
- "kind": "IDENTIFIER",
- "name": "JSON",
- "startPosition": "3470"
- },
- "endPosition": "3484",
- "kind": "MEMBER_SELECT",
- "startPosition": "3470"
- },
- "arguments": [
- {
- "endPosition": "3489",
- "kind": "IDENTIFIER",
- "name": "tree",
- "startPosition": "3485"
- },
- {
- "endPosition": "3495",
- "kind": "NULL_LITERAL",
- "startPosition": "3491"
- },
- {
- "endPosition": "3498",
- "kind": "NUMBER_LITERAL",
- "value": "2",
- "startPosition": "3497"
- }
- ],
- "startPosition": "3470"
- }
- ],
- "startPosition": "3464"
- },
- "endPosition": "3500",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3464"
- },
- {
- "expression": {
- "endPosition": "3527",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3522",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3517"
- },
- "arguments": [
- {
- "endPosition": "3525",
- "kind": "STRING_LITERAL",
- "value": ",",
- "startPosition": "3524"
- }
- ],
- "startPosition": "3517"
- },
- "endPosition": "3527",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3517"
- }
- ],
- "startPosition": "3447"
- }
- }
- ],
- "startPosition": "3100"
- }
- }
- ],
- "startPosition": "3060"
- },
- "startPosition": "3031"
- }
- ],
- "startPosition": "2897"
- },
- "strict": "false",
- "startPosition": "2867",
- "parameters": [
- {
- "endPosition": "2895",
- "kind": "IDENTIFIER",
- "name": "subdir",
- "startPosition": "2889"
- }
- ]
- },
- {
- "endPosition": "3901",
- "kind": "FUNCTION",
- "name": "main",
- "body": {
- "endPosition": "3899",
- "kind": "BLOCK",
- "statements": [
- {
- "expression": {
- "endPosition": "3631",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3626",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3621"
- },
- "arguments": [
- {
- "endPosition": "3629",
- "kind": "STRING_LITERAL",
- "value": "[",
- "startPosition": "3628"
- }
- ],
- "startPosition": "3621"
- },
- "endPosition": "3631",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3621"
- },
- {
- "expression": {
- "endPosition": "3665",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3650",
- "kind": "IDENTIFIER",
- "name": "processFiles",
- "startPosition": "3638"
- },
- "arguments": [
- {
- "endPosition": "3663",
- "kind": "STRING_LITERAL",
- "value": "parsertests",
- "startPosition": "3652"
- }
- ],
- "startPosition": "3638"
- },
- "endPosition": "3665",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3638"
- },
- {
- "expression": {
- "endPosition": "3706",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3683",
- "kind": "IDENTIFIER",
- "name": "processFiles",
- "startPosition": "3671"
- },
- "arguments": [
- {
- "endPosition": "3704",
- "kind": "STRING_LITERAL",
- "value": "parsernegativetests",
- "startPosition": "3685"
- }
- ],
- "startPosition": "3671"
- },
- "endPosition": "3706",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3671"
- },
- {
- "endPosition": "3775",
- "kind": "VARIABLE",
- "name": "script",
- "startPosition": "3747",
- "initializer": {
- "endPosition": "3775",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3765",
- "kind": "IDENTIFIER",
- "name": "readFully",
- "startPosition": "3756"
- },
- "arguments": [
- {
- "endPosition": "3774",
- "kind": "IDENTIFIER",
- "name": "__FILE__",
- "startPosition": "3766"
- }
- ],
- "startPosition": "3756"
- }
- },
- {
- "endPosition": "3840",
- "kind": "VARIABLE",
- "name": "tree",
- "startPosition": "3785",
- "initializer": {
- "endPosition": "3840",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "parse",
- "expression": {
- "constructorExpression": {
- "endPosition": "3804",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3802",
- "kind": "IDENTIFIER",
- "name": "Parser",
- "startPosition": "3796"
- },
- "arguments": [],
- "startPosition": "3796"
- },
- "endPosition": "3804",
- "kind": "NEW",
- "startPosition": "3792"
- },
- "endPosition": "3810",
- "kind": "MEMBER_SELECT",
- "startPosition": "3792"
- },
- "arguments": [
- {
- "endPosition": "3824",
- "kind": "STRING_LITERAL",
- "value": "parserapi.js",
- "startPosition": "3812"
- },
- {
- "endPosition": "3833",
- "kind": "IDENTIFIER",
- "name": "script",
- "startPosition": "3827"
- },
- {
- "endPosition": "3839",
- "kind": "NULL_LITERAL",
- "startPosition": "3835"
- }
- ],
- "startPosition": "3792"
- }
- },
- {
- "expression": {
- "endPosition": "3882",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3851",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3846"
- },
- "arguments": [
- {
- "endPosition": "3881",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "identifier": "stringify",
- "expression": {
- "endPosition": "3856",
- "kind": "IDENTIFIER",
- "name": "JSON",
- "startPosition": "3852"
- },
- "endPosition": "3866",
- "kind": "MEMBER_SELECT",
- "startPosition": "3852"
- },
- "arguments": [
- {
- "endPosition": "3871",
- "kind": "IDENTIFIER",
- "name": "tree",
- "startPosition": "3867"
- },
- {
- "endPosition": "3877",
- "kind": "NULL_LITERAL",
- "startPosition": "3873"
- },
- {
- "endPosition": "3880",
- "kind": "NUMBER_LITERAL",
- "value": "2",
- "startPosition": "3879"
- }
- ],
- "startPosition": "3852"
- }
- ],
- "startPosition": "3846"
- },
- "endPosition": "3882",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3846"
- },
- {
- "expression": {
- "endPosition": "3898",
- "kind": "FUNCTION_INVOCATION",
- "functionSelect": {
- "endPosition": "3893",
- "kind": "IDENTIFIER",
- "name": "print",
- "startPosition": "3888"
- },
- "arguments": [
- {
- "endPosition": "3896",
- "kind": "STRING_LITERAL",
- "value": "]",
- "startPosition": "3895"
- }
- ],
- "startPosition": "3888"
- },
- "endPosition": "3898",
- "kind": "EXPRESSION_STATEMENT",
- "startPosition": "3888"
- }
- ],
- "startPosition": "3615"
- },
- "strict": "false",
- "startPosition": "3599",
- "parameters": []
- },
- {
"expression": {
"expression": {
"endPosition": "1305",
@@ -6991,6 +6189,808 @@
"startPosition": "1972"
},
{
+ "endPosition": "3598",
+ "kind": "FUNCTION",
+ "name": "processFiles",
+ "body": {
+ "endPosition": "3555",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "endPosition": "2938",
+ "kind": "VARIABLE",
+ "name": "File",
+ "startPosition": "2906",
+ "initializer": {
+ "endPosition": "2938",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "type",
+ "expression": {
+ "endPosition": "2917",
+ "kind": "IDENTIFIER",
+ "name": "Java",
+ "startPosition": "2913"
+ },
+ "endPosition": "2922",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "2913"
+ },
+ "arguments": [
+ {
+ "endPosition": "2936",
+ "kind": "STRING_LITERAL",
+ "value": "java.io.File",
+ "startPosition": "2924"
+ }
+ ],
+ "startPosition": "2913"
+ }
+ },
+ {
+ "endPosition": "2993",
+ "kind": "VARIABLE",
+ "name": "files",
+ "startPosition": "2947",
+ "initializer": {
+ "endPosition": "2993",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "listFiles",
+ "expression": {
+ "constructorExpression": {
+ "endPosition": "2981",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "2963",
+ "kind": "IDENTIFIER",
+ "name": "File",
+ "startPosition": "2959"
+ },
+ "arguments": [
+ {
+ "leftOperand": {
+ "endPosition": "2971",
+ "kind": "IDENTIFIER",
+ "name": "__DIR__",
+ "startPosition": "2964"
+ },
+ "endPosition": "2980",
+ "kind": "PLUS",
+ "rightOperand": {
+ "endPosition": "2980",
+ "kind": "IDENTIFIER",
+ "name": "subdir",
+ "startPosition": "2974"
+ },
+ "startPosition": "2964"
+ }
+ ],
+ "startPosition": "2959"
+ },
+ "endPosition": "2981",
+ "kind": "NEW",
+ "startPosition": "2955"
+ },
+ "endPosition": "2991",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "2955"
+ },
+ "arguments": [],
+ "startPosition": "2955"
+ }
+ },
+ {
+ "expression": {
+ "endPosition": "3026",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "sort",
+ "expression": {
+ "identifier": "Arrays",
+ "expression": {
+ "identifier": "util",
+ "expression": {
+ "endPosition": "3002",
+ "kind": "IDENTIFIER",
+ "name": "java",
+ "startPosition": "2998"
+ },
+ "endPosition": "3007",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "2998"
+ },
+ "endPosition": "3014",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "2998"
+ },
+ "endPosition": "3019",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "2998"
+ },
+ "arguments": [
+ {
+ "endPosition": "3025",
+ "kind": "IDENTIFIER",
+ "name": "files",
+ "startPosition": "3020"
+ }
+ ],
+ "startPosition": "2998"
+ },
+ "endPosition": "3026",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "2998"
+ },
+ {
+ "endPosition": "3049",
+ "kind": "VARIABLE",
+ "name": "file",
+ "startPosition": "3045"
+ },
+ {
+ "expression": {
+ "endPosition": "3058",
+ "kind": "IDENTIFIER",
+ "name": "files",
+ "startPosition": "3053"
+ },
+ "endPosition": "3555",
+ "kind": "FOR_IN_LOOP",
+ "forEach": "true",
+ "variable": {
+ "endPosition": "3049",
+ "kind": "IDENTIFIER",
+ "name": "file",
+ "startPosition": "3045"
+ },
+ "statement": {
+ "endPosition": "3555",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": {
+ "endPosition": "3098",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "endsWith",
+ "expression": {
+ "identifier": "name",
+ "expression": {
+ "endPosition": "3077",
+ "kind": "IDENTIFIER",
+ "name": "file",
+ "startPosition": "3073"
+ },
+ "endPosition": "3082",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3073"
+ },
+ "endPosition": "3091",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3073"
+ },
+ "arguments": [
+ {
+ "endPosition": "3096",
+ "kind": "STRING_LITERAL",
+ "value": ".js",
+ "startPosition": "3093"
+ }
+ ],
+ "startPosition": "3073"
+ },
+ "endPosition": "3550",
+ "kind": "IF",
+ "startPosition": "3069",
+ "thenStatement": {
+ "endPosition": "3550",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "endPosition": "3141",
+ "kind": "VARIABLE",
+ "name": "script",
+ "startPosition": "3117",
+ "initializer": {
+ "endPosition": "3141",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3135",
+ "kind": "IDENTIFIER",
+ "name": "readFully",
+ "startPosition": "3126"
+ },
+ "arguments": [
+ {
+ "endPosition": "3140",
+ "kind": "IDENTIFIER",
+ "name": "file",
+ "startPosition": "3136"
+ }
+ ],
+ "startPosition": "3126"
+ }
+ },
+ {
+ "endPosition": "3179",
+ "kind": "VARIABLE",
+ "name": "parser",
+ "startPosition": "3158",
+ "initializer": {
+ "constructorExpression": {
+ "endPosition": "3179",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3177",
+ "kind": "IDENTIFIER",
+ "name": "Parser",
+ "startPosition": "3171"
+ },
+ "arguments": [],
+ "startPosition": "3171"
+ },
+ "endPosition": "3179",
+ "kind": "NEW",
+ "startPosition": "3167"
+ }
+ },
+ {
+ "endPosition": "3415",
+ "kind": "VARIABLE",
+ "name": "tree",
+ "startPosition": "3196",
+ "initializer": {
+ "endPosition": "3415",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "parse",
+ "expression": {
+ "endPosition": "3209",
+ "kind": "IDENTIFIER",
+ "name": "parser",
+ "startPosition": "3203"
+ },
+ "endPosition": "3215",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3203"
+ },
+ "arguments": [
+ {
+ "leftOperand": {
+ "leftOperand": {
+ "endPosition": "3222",
+ "kind": "IDENTIFIER",
+ "name": "subdir",
+ "startPosition": "3216"
+ },
+ "endPosition": "3227",
+ "kind": "PLUS",
+ "rightOperand": {
+ "endPosition": "3227",
+ "kind": "STRING_LITERAL",
+ "value": "/",
+ "startPosition": "3226"
+ },
+ "startPosition": "3216"
+ },
+ "endPosition": "3240",
+ "kind": "PLUS",
+ "rightOperand": {
+ "identifier": "name",
+ "expression": {
+ "endPosition": "3235",
+ "kind": "IDENTIFIER",
+ "name": "file",
+ "startPosition": "3231"
+ },
+ "endPosition": "3240",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3231"
+ },
+ "startPosition": "3216"
+ },
+ {
+ "endPosition": "3248",
+ "kind": "IDENTIFIER",
+ "name": "script",
+ "startPosition": "3242"
+ },
+ {
+ "endPosition": "3286",
+ "kind": "FUNCTION_EXPRESSION",
+ "body": {
+ "endPosition": "3397",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "3365",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3312",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3307"
+ },
+ "arguments": [
+ {
+ "endPosition": "3364",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "stringify",
+ "expression": {
+ "endPosition": "3317",
+ "kind": "IDENTIFIER",
+ "name": "JSON",
+ "startPosition": "3313"
+ },
+ "endPosition": "3327",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3313"
+ },
+ "arguments": [
+ {
+ "endPosition": "3354",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "convert",
+ "expression": {
+ "endPosition": "3334",
+ "kind": "IDENTIFIER",
+ "name": "parser",
+ "startPosition": "3328"
+ },
+ "endPosition": "3342",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3328"
+ },
+ "arguments": [
+ {
+ "endPosition": "3353",
+ "kind": "IDENTIFIER",
+ "name": "diagnostic",
+ "startPosition": "3343"
+ }
+ ],
+ "startPosition": "3328"
+ },
+ {
+ "endPosition": "3360",
+ "kind": "NULL_LITERAL",
+ "startPosition": "3356"
+ },
+ {
+ "endPosition": "3363",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "3362"
+ }
+ ],
+ "startPosition": "3313"
+ }
+ ],
+ "startPosition": "3307"
+ },
+ "endPosition": "3365",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3307"
+ },
+ {
+ "expression": {
+ "endPosition": "3396",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3391",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3386"
+ },
+ "arguments": [
+ {
+ "endPosition": "3394",
+ "kind": "STRING_LITERAL",
+ "value": ",",
+ "startPosition": "3393"
+ }
+ ],
+ "startPosition": "3386"
+ },
+ "endPosition": "3396",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3386"
+ }
+ ],
+ "startPosition": "3286"
+ },
+ "strict": "false",
+ "startPosition": "3286",
+ "parameters": [
+ {
+ "endPosition": "3284",
+ "kind": "IDENTIFIER",
+ "name": "diagnostic",
+ "startPosition": "3274"
+ }
+ ]
+ }
+ ],
+ "startPosition": "3203"
+ }
+ },
+ {
+ "condition": {
+ "leftOperand": {
+ "endPosition": "3437",
+ "kind": "IDENTIFIER",
+ "name": "tree",
+ "startPosition": "3433"
+ },
+ "endPosition": "3445",
+ "kind": "NOT_EQUAL_TO",
+ "rightOperand": {
+ "endPosition": "3445",
+ "kind": "NULL_LITERAL",
+ "startPosition": "3441"
+ },
+ "startPosition": "3433"
+ },
+ "endPosition": "3541",
+ "kind": "IF",
+ "startPosition": "3429",
+ "thenStatement": {
+ "endPosition": "3541",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "3500",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3469",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3464"
+ },
+ "arguments": [
+ {
+ "endPosition": "3499",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "stringify",
+ "expression": {
+ "endPosition": "3474",
+ "kind": "IDENTIFIER",
+ "name": "JSON",
+ "startPosition": "3470"
+ },
+ "endPosition": "3484",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3470"
+ },
+ "arguments": [
+ {
+ "endPosition": "3489",
+ "kind": "IDENTIFIER",
+ "name": "tree",
+ "startPosition": "3485"
+ },
+ {
+ "endPosition": "3495",
+ "kind": "NULL_LITERAL",
+ "startPosition": "3491"
+ },
+ {
+ "endPosition": "3498",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "3497"
+ }
+ ],
+ "startPosition": "3470"
+ }
+ ],
+ "startPosition": "3464"
+ },
+ "endPosition": "3500",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3464"
+ },
+ {
+ "expression": {
+ "endPosition": "3527",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3522",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3517"
+ },
+ "arguments": [
+ {
+ "endPosition": "3525",
+ "kind": "STRING_LITERAL",
+ "value": ",",
+ "startPosition": "3524"
+ }
+ ],
+ "startPosition": "3517"
+ },
+ "endPosition": "3527",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3517"
+ }
+ ],
+ "startPosition": "3447"
+ }
+ }
+ ],
+ "startPosition": "3100"
+ }
+ }
+ ],
+ "startPosition": "3060"
+ },
+ "startPosition": "3031"
+ }
+ ],
+ "startPosition": "2897"
+ },
+ "strict": "false",
+ "startPosition": "2867",
+ "parameters": [
+ {
+ "endPosition": "2895",
+ "kind": "IDENTIFIER",
+ "name": "subdir",
+ "startPosition": "2889"
+ }
+ ]
+ },
+ {
+ "endPosition": "3901",
+ "kind": "FUNCTION",
+ "name": "main",
+ "body": {
+ "endPosition": "3899",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "3631",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3626",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3621"
+ },
+ "arguments": [
+ {
+ "endPosition": "3629",
+ "kind": "STRING_LITERAL",
+ "value": "[",
+ "startPosition": "3628"
+ }
+ ],
+ "startPosition": "3621"
+ },
+ "endPosition": "3631",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3621"
+ },
+ {
+ "expression": {
+ "endPosition": "3665",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3650",
+ "kind": "IDENTIFIER",
+ "name": "processFiles",
+ "startPosition": "3638"
+ },
+ "arguments": [
+ {
+ "endPosition": "3663",
+ "kind": "STRING_LITERAL",
+ "value": "parsertests",
+ "startPosition": "3652"
+ }
+ ],
+ "startPosition": "3638"
+ },
+ "endPosition": "3665",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3638"
+ },
+ {
+ "expression": {
+ "endPosition": "3706",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3683",
+ "kind": "IDENTIFIER",
+ "name": "processFiles",
+ "startPosition": "3671"
+ },
+ "arguments": [
+ {
+ "endPosition": "3704",
+ "kind": "STRING_LITERAL",
+ "value": "parsernegativetests",
+ "startPosition": "3685"
+ }
+ ],
+ "startPosition": "3671"
+ },
+ "endPosition": "3706",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3671"
+ },
+ {
+ "endPosition": "3775",
+ "kind": "VARIABLE",
+ "name": "script",
+ "startPosition": "3747",
+ "initializer": {
+ "endPosition": "3775",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3765",
+ "kind": "IDENTIFIER",
+ "name": "readFully",
+ "startPosition": "3756"
+ },
+ "arguments": [
+ {
+ "endPosition": "3774",
+ "kind": "IDENTIFIER",
+ "name": "__FILE__",
+ "startPosition": "3766"
+ }
+ ],
+ "startPosition": "3756"
+ }
+ },
+ {
+ "endPosition": "3840",
+ "kind": "VARIABLE",
+ "name": "tree",
+ "startPosition": "3785",
+ "initializer": {
+ "endPosition": "3840",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "parse",
+ "expression": {
+ "constructorExpression": {
+ "endPosition": "3804",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3802",
+ "kind": "IDENTIFIER",
+ "name": "Parser",
+ "startPosition": "3796"
+ },
+ "arguments": [],
+ "startPosition": "3796"
+ },
+ "endPosition": "3804",
+ "kind": "NEW",
+ "startPosition": "3792"
+ },
+ "endPosition": "3810",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3792"
+ },
+ "arguments": [
+ {
+ "endPosition": "3824",
+ "kind": "STRING_LITERAL",
+ "value": "parserapi.js",
+ "startPosition": "3812"
+ },
+ {
+ "endPosition": "3833",
+ "kind": "IDENTIFIER",
+ "name": "script",
+ "startPosition": "3827"
+ },
+ {
+ "endPosition": "3839",
+ "kind": "NULL_LITERAL",
+ "startPosition": "3835"
+ }
+ ],
+ "startPosition": "3792"
+ }
+ },
+ {
+ "expression": {
+ "endPosition": "3882",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3851",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3846"
+ },
+ "arguments": [
+ {
+ "endPosition": "3881",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "stringify",
+ "expression": {
+ "endPosition": "3856",
+ "kind": "IDENTIFIER",
+ "name": "JSON",
+ "startPosition": "3852"
+ },
+ "endPosition": "3866",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "3852"
+ },
+ "arguments": [
+ {
+ "endPosition": "3871",
+ "kind": "IDENTIFIER",
+ "name": "tree",
+ "startPosition": "3867"
+ },
+ {
+ "endPosition": "3877",
+ "kind": "NULL_LITERAL",
+ "startPosition": "3873"
+ },
+ {
+ "endPosition": "3880",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "3879"
+ }
+ ],
+ "startPosition": "3852"
+ }
+ ],
+ "startPosition": "3846"
+ },
+ "endPosition": "3882",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3846"
+ },
+ {
+ "expression": {
+ "endPosition": "3898",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "3893",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "3888"
+ },
+ "arguments": [
+ {
+ "endPosition": "3896",
+ "kind": "STRING_LITERAL",
+ "value": "]",
+ "startPosition": "3895"
+ }
+ ],
+ "startPosition": "3888"
+ },
+ "endPosition": "3898",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "3888"
+ }
+ ],
+ "startPosition": "3615"
+ },
+ "strict": "false",
+ "startPosition": "3599",
+ "parameters": []
+ },
+ {
"expression": {
"endPosition": "3909",
"kind": "FUNCTION_INVOCATION",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/array_access.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation array access tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+ array[1]
+
+ { array[test()] }
+
+ function a () {
+ array[null]
+ }
+
+ var x = {
+ test1 : array[-1],
+ test2 : [array[array[NaN]]]
+ }
+EOF
+
+parse("array_access.js", code, "-nse", new (Java.extend(visitor, {
+ visitArrayAccess : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/array_access.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,109 @@
+[
+ {
+ "expression": {
+ "endPosition": "9",
+ "kind": "IDENTIFIER",
+ "name": "array",
+ "startPosition": "4"
+ },
+ "endPosition": "12",
+ "kind": "ARRAY_ACCESS",
+ "index": {
+ "endPosition": "11",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "10"
+ },
+ "startPosition": "4"
+ },
+ {
+ "expression": {
+ "endPosition": "25",
+ "kind": "IDENTIFIER",
+ "name": "array",
+ "startPosition": "20"
+ },
+ "endPosition": "33",
+ "kind": "ARRAY_ACCESS",
+ "index": {
+ "endPosition": "32",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "30",
+ "kind": "IDENTIFIER",
+ "name": "test",
+ "startPosition": "26"
+ },
+ "arguments": [],
+ "startPosition": "26"
+ },
+ "startPosition": "20"
+ },
+ {
+ "expression": {
+ "endPosition": "70",
+ "kind": "IDENTIFIER",
+ "name": "array",
+ "startPosition": "65"
+ },
+ "endPosition": "76",
+ "kind": "ARRAY_ACCESS",
+ "index": {
+ "endPosition": "75",
+ "kind": "NULL_LITERAL",
+ "value": "null",
+ "startPosition": "71"
+ },
+ "startPosition": "65"
+ },
+ {
+ "expression": {
+ "endPosition": "119",
+ "kind": "IDENTIFIER",
+ "name": "array",
+ "startPosition": "114"
+ },
+ "endPosition": "123",
+ "kind": "ARRAY_ACCESS",
+ "index": {
+ "expression": {
+ "endPosition": "122",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "121"
+ },
+ "endPosition": "122",
+ "kind": "MINUS",
+ "startPosition": "120"
+ },
+ "startPosition": "114"
+ },
+ {
+ "expression": {
+ "endPosition": "147",
+ "kind": "IDENTIFIER",
+ "name": "array",
+ "startPosition": "142"
+ },
+ "endPosition": "159",
+ "kind": "ARRAY_ACCESS",
+ "index": {
+ "expression": {
+ "endPosition": "153",
+ "kind": "IDENTIFIER",
+ "name": "array",
+ "startPosition": "148"
+ },
+ "endPosition": "158",
+ "kind": "ARRAY_ACCESS",
+ "index": {
+ "endPosition": "157",
+ "kind": "IDENTIFIER",
+ "name": "NaN",
+ "startPosition": "154"
+ },
+ "startPosition": "148"
+ },
+ "startPosition": "142"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/array_literal.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation array literal tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+var x = [];
+var y = [1, 43, 5, 45,];
+var z = [34,,,4];
+var k = [ {}, { x: 3 }, "hello" ];
+
+EOF
+
+
+parse("array_literal.js", code, "-nse", new (Java.extend(visitor, {
+ visitArrayLiteral : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,105 @@
+[
+ {
+ "endPosition": "11",
+ "kind": "ARRAY_LITERAL",
+ "elements": [],
+ "startPosition": "9"
+ },
+ {
+ "endPosition": "36",
+ "kind": "ARRAY_LITERAL",
+ "elements": [
+ {
+ "endPosition": "23",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "22"
+ },
+ {
+ "endPosition": "27",
+ "kind": "NUMBER_LITERAL",
+ "value": "43",
+ "startPosition": "25"
+ },
+ {
+ "endPosition": "30",
+ "kind": "NUMBER_LITERAL",
+ "value": "5",
+ "startPosition": "29"
+ },
+ {
+ "endPosition": "34",
+ "kind": "NUMBER_LITERAL",
+ "value": "45",
+ "startPosition": "32"
+ }
+ ],
+ "startPosition": "21"
+ },
+ {
+ "endPosition": "54",
+ "kind": "ARRAY_LITERAL",
+ "elements": [
+ {
+ "endPosition": "49",
+ "kind": "NUMBER_LITERAL",
+ "value": "34",
+ "startPosition": "47"
+ },
+ null,
+ null,
+ {
+ "endPosition": "53",
+ "kind": "NUMBER_LITERAL",
+ "value": "4",
+ "startPosition": "52"
+ }
+ ],
+ "startPosition": "46"
+ },
+ {
+ "endPosition": "89",
+ "kind": "ARRAY_LITERAL",
+ "elements": [
+ {
+ "endPosition": "68",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "66",
+ "properties": []
+ },
+ {
+ "endPosition": "78",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "70",
+ "properties": [
+ {
+ "getter": "null",
+ "endPosition": "74",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "76",
+ "kind": "NUMBER_LITERAL",
+ "value": "3",
+ "startPosition": "75"
+ },
+ "startPosition": "72",
+ "key": {
+ "endPosition": "73",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "72"
+ }
+ }
+ ]
+ },
+ {
+ "endPosition": "86",
+ "kind": "STRING_LITERAL",
+ "value": "hello",
+ "startPosition": "81"
+ }
+ ],
+ "startPosition": "64"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/assignment.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 assignment expression tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+a = 1
+b = 2;
+c = {}
+d = undefined
+e = NaN
+f = function () {}
+g = function () {"use strict";}
+
+EOF
+
+parse("assignment.js", code, "-nse", new (Java.extend(visitor, {
+ visitAssignment : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/assignment.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,149 @@
+[
+ {
+ "expression": {
+ "endPosition": "5",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "4"
+ },
+ "endPosition": "5",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "1",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "0"
+ },
+ "startPosition": "0"
+ },
+ {
+ "expression": {
+ "endPosition": "11",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "10"
+ },
+ "endPosition": "11",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "7",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "6"
+ },
+ "startPosition": "6"
+ },
+ {
+ "expression": {
+ "endPosition": "19",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "17",
+ "properties": []
+ },
+ "endPosition": "19",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "14",
+ "kind": "IDENTIFIER",
+ "name": "c",
+ "startPosition": "13"
+ },
+ "startPosition": "13"
+ },
+ {
+ "expression": {
+ "endPosition": "33",
+ "kind": "IDENTIFIER",
+ "name": "undefined",
+ "startPosition": "24"
+ },
+ "endPosition": "33",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "21",
+ "kind": "IDENTIFIER",
+ "name": "d",
+ "startPosition": "20"
+ },
+ "startPosition": "20"
+ },
+ {
+ "expression": {
+ "endPosition": "41",
+ "kind": "IDENTIFIER",
+ "name": "NaN",
+ "startPosition": "38"
+ },
+ "endPosition": "41",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "35",
+ "kind": "IDENTIFIER",
+ "name": "e",
+ "startPosition": "34"
+ },
+ "startPosition": "34"
+ },
+ {
+ "expression": {
+ "endPosition": "58",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "59",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "58"
+ },
+ "strict": "false",
+ "startPosition": "58",
+ "parameters": []
+ },
+ "endPosition": "58",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "43",
+ "kind": "IDENTIFIER",
+ "name": "f",
+ "startPosition": "42"
+ },
+ "startPosition": "42"
+ },
+ {
+ "expression": {
+ "endPosition": "77",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "91",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "89",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "79"
+ },
+ "endPosition": "89",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "79"
+ }
+ ],
+ "startPosition": "77"
+ },
+ "strict": "true",
+ "startPosition": "77",
+ "parameters": []
+ },
+ "endPosition": "77",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "62",
+ "kind": "IDENTIFIER",
+ "name": "g",
+ "startPosition": "61"
+ },
+ "startPosition": "61"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/assignmentExpr.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/**
+ * Tests to check representation assignment expression tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+xyz += 314;
+xyz -= 314;
+xyz *= 314;
+xyz /= 314;
+xyz %= 314;
+xyz <<= 314;
+xyz >>= 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/assignmentExpr.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -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"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 = <<EOF
+a * b
+a / b;
+a % b;
+a + b;
+a - b;
+a << b;
+a >> 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/binaryExpr.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -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"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/block.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 = <<EOF
+{}
+{ print("hello"); }
+function a () {
+ return 2 + 1;
+}
+EOF
+
+
+parse("block.js", code, "-nse", new (Java.extend(visitor, {
+ visitBlock : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/block.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,68 @@
+[
+ {
+ "endPosition": "2",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "0"
+ },
+ {
+ "endPosition": "22",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "19",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "10",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "5"
+ },
+ "arguments": [
+ {
+ "endPosition": "17",
+ "kind": "STRING_LITERAL",
+ "value": "hello",
+ "startPosition": "12"
+ }
+ ],
+ "startPosition": "5"
+ },
+ "endPosition": "19",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "5"
+ }
+ ],
+ "startPosition": "3"
+ },
+ {
+ "endPosition": "56",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "leftOperand": {
+ "endPosition": "51",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "50"
+ },
+ "endPosition": "55",
+ "kind": "PLUS",
+ "rightOperand": {
+ "endPosition": "55",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "54"
+ },
+ "startPosition": "50"
+ },
+ "endPosition": "56",
+ "kind": "RETURN",
+ "startPosition": "43"
+ }
+ ],
+ "startPosition": "37"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/breakStat.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,56 @@
+/*
+ * 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 break statement tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+while (true) { break; };
+loop: { while (true) { break loop } };
+loop: { for (;;) { break loop } };
+do break; while(true)
+switch(a) {
+ case 1:
+ case 2:
+ break
+ default:
+ break;
+}
+
+
+EOF
+
+
+parse("breakStat.js", code, "-nse", new (Java.extend(visitor, {
+ visitBreak : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/breakStat.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,38 @@
+[
+ {
+ "endPosition": "21",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "15"
+ },
+ {
+ "endPosition": "58",
+ "kind": "BREAK",
+ "label": "loop",
+ "startPosition": "48"
+ },
+ {
+ "endPosition": "93",
+ "kind": "BREAK",
+ "label": "loop",
+ "startPosition": "83"
+ },
+ {
+ "endPosition": "108",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "102"
+ },
+ {
+ "endPosition": "170",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "165"
+ },
+ {
+ "endPosition": "198",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "192"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/case.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation case tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+switch (e) {
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+}
+label:
+switch (a) {
+ case 1:
+ break
+ case 2:
+ break label
+ case 3:
+ break
+}
+
+EOF
+
+parse("breakStat.js", code, "-nse", new (Java.extend(visitor, {
+ visitCase : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/case.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,109 @@
+[
+ {
+ "expression": {
+ "endPosition": "23",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "22"
+ },
+ "endPosition": "24",
+ "kind": "CASE",
+ "statements": [],
+ "startPosition": "17"
+ },
+ {
+ "expression": {
+ "endPosition": "35",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "34"
+ },
+ "endPosition": "36",
+ "kind": "CASE",
+ "statements": [],
+ "startPosition": "29"
+ },
+ {
+ "expression": {
+ "endPosition": "47",
+ "kind": "NUMBER_LITERAL",
+ "value": "3",
+ "startPosition": "46"
+ },
+ "endPosition": "63",
+ "kind": "CASE",
+ "statements": [
+ {
+ "endPosition": "63",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "57"
+ }
+ ],
+ "startPosition": "41"
+ },
+ {
+ "expression": "null",
+ "endPosition": "77",
+ "kind": "CASE",
+ "statements": [],
+ "startPosition": "69"
+ },
+ {
+ "expression": {
+ "endPosition": "110",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "109"
+ },
+ "endPosition": "125",
+ "kind": "CASE",
+ "statements": [
+ {
+ "endPosition": "125",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "120"
+ }
+ ],
+ "startPosition": "104"
+ },
+ {
+ "expression": {
+ "endPosition": "136",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "135"
+ },
+ "endPosition": "157",
+ "kind": "CASE",
+ "statements": [
+ {
+ "endPosition": "157",
+ "kind": "BREAK",
+ "label": "label",
+ "startPosition": "146"
+ }
+ ],
+ "startPosition": "130"
+ },
+ {
+ "expression": {
+ "endPosition": "168",
+ "kind": "NUMBER_LITERAL",
+ "value": "3",
+ "startPosition": "167"
+ },
+ "endPosition": "183",
+ "kind": "CASE",
+ "statements": [
+ {
+ "endPosition": "183",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "178"
+ }
+ ],
+ "startPosition": "162"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/compilationUnitTree.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,41 @@
+/*
+ * 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 all tree
+ *
+ * @bug 8068306
+ * @subtest
+ */
+
+var a = 1
+var b = function () {
+ print(a)
+}
+
+var c = {
+ x : function (a, b, c) {
+ return a * b - c;
+ },
+ i : []
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/condExpr.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * 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 case tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+a? b : c;
+
+EOF
+
+parse("condExpr.js", code, "-nse", new (Java.extend(visitor, {
+ visitConditionalExpression : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/condExpr.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,25 @@
+[
+ {
+ "condition": {
+ "endPosition": "2",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "1"
+ },
+ "endPosition": "9",
+ "kind": "CONDITIONAL_EXPRESSION",
+ "trueExpression": {
+ "endPosition": "5",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "4"
+ },
+ "falseExpression": {
+ "endPosition": "9",
+ "kind": "IDENTIFIER",
+ "name": "c",
+ "startPosition": "8"
+ },
+ "startPosition": "2"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/continueStat.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation continue tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+while (true) { continue; };
+begin: { while (true) { continue begin; } };
+start: { for(;;) { continue start; } };
+do continue; while(false)
+label:do continue label; while(true)
+
+EOF
+
+parse("continueStat.js", code, "-nse", new (Java.extend(visitor, {
+ visitContinue : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/continueStat.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,32 @@
+[
+ {
+ "endPosition": "25",
+ "kind": "CONTINUE",
+ "label": "null",
+ "startPosition": "16"
+ },
+ {
+ "endPosition": "68",
+ "kind": "CONTINUE",
+ "label": "begin",
+ "startPosition": "53"
+ },
+ {
+ "endPosition": "108",
+ "kind": "CONTINUE",
+ "label": "start",
+ "startPosition": "93"
+ },
+ {
+ "endPosition": "126",
+ "kind": "CONTINUE",
+ "label": "null",
+ "startPosition": "117"
+ },
+ {
+ "endPosition": "164",
+ "kind": "CONTINUE",
+ "label": "label",
+ "startPosition": "149"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/debuggerStat.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * 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 continue tree.
+ *
+ * @bug 8068306
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+debugger;
+
+EOF
+
+parse("debugger.js", code, "-nse", new (Java.extend(visitor, {
+ visitDebugger : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/debuggerStat.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,7 @@
+[
+ {
+ "endPosition": "9",
+ "kind": "DEBUGGER",
+ "startPosition": "0"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/diagnostic.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,78 @@
+/*
+ * 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 8068304
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+ var a = { k:1, k:2 }
+EOF
+
+parseDiagnostic(code, "-strict")
+
+var code = <<EOF
+ var x = {}
+ with(x) {}
+EOF
+
+parseDiagnostic(code, "-strict")
+
+var code = <<EOF
+ var eval = "test value";
+EOF
+
+parseDiagnostic(code, "-strict")
+
+var code = <<EOF
+ var arguments = "test value";
+EOF
+
+parseDiagnostic(code, "-strict")
+
+var code = <<EOF
+ if (true) {
+ function a () {}
+ }
+EOF
+
+parseDiagnostic(code, "-strict")
+
+var code = <<EOF
+ var a = { get x() {}, get x() {}};
+ var a = { set x() {}, set x() {}};
+EOF
+
+parseDiagnostic(code, "-strict")
+
+var code = <<EOF
+ /([a-z])+(/;
+ /([a-z])+/h;
+EOF
+
+parseDiagnostic(code, "-strict")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/diagnostic.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,95 @@
+[
+ {
+ "fileName": "test.js",
+ "code": "ident (19, 1)",
+ "columnNumber": "19",
+ "kind": "ERROR",
+ "position": "19",
+ "message": "test.js:1:19 Property \"k\" already defined\n var a = { k:1, k:2 }\n ^",
+ "lineNumber": "1"
+ }
+]
+[
+ {
+ "fileName": "test.js",
+ "code": "with (19, 4)",
+ "columnNumber": "4",
+ "kind": "ERROR",
+ "position": "19",
+ "message": "test.js:2:4 \"with\" statement cannot be used in strict mode\n with(x) {}\n ^",
+ "lineNumber": "2"
+ }
+]
+[
+ {
+ "fileName": "test.js",
+ "code": "ident (8, 4)",
+ "columnNumber": "8",
+ "kind": "ERROR",
+ "position": "8",
+ "message": "test.js:1:8 \"eval\" cannot be used as variable name in strict mode\n var eval = \"test value\";\n ^",
+ "lineNumber": "1"
+ }
+]
+[
+ {
+ "fileName": "test.js",
+ "code": "ident (8, 9)",
+ "columnNumber": "8",
+ "kind": "ERROR",
+ "position": "8",
+ "message": "test.js:1:8 \"arguments\" cannot be used as variable name in strict mode\n var arguments = \"test value\";\n ^",
+ "lineNumber": "1"
+ }
+]
+[
+ {
+ "fileName": "test.js",
+ "code": "function (23, 8)",
+ "columnNumber": "6",
+ "kind": "ERROR",
+ "position": "23",
+ "message": "test.js:2:6 In strict mode, function declarations can only occur at program or function body level. You should use a function expression here instead.\n \t\tfunction a () {}\n \t\t^",
+ "lineNumber": "2"
+ }
+]
+[
+ {
+ "fileName": "test.js",
+ "code": "ident (26, 3)",
+ "columnNumber": "26",
+ "kind": "ERROR",
+ "position": "26",
+ "message": "test.js:1:26 Property \"x\" already defined\n var a = { get x() {}, get x() {}};\n ^",
+ "lineNumber": "1"
+ },
+ {
+ "fileName": "test.js",
+ "code": "ident (65, 3)",
+ "columnNumber": "26",
+ "kind": "ERROR",
+ "position": "65",
+ "message": "test.js:2:26 Property \"x\" already defined\n var a = { set x() {}, set x() {}};\n ^",
+ "lineNumber": "2"
+ }
+]
+[
+ {
+ "fileName": "test.js",
+ "code": "; (15, 1)",
+ "columnNumber": "15",
+ "kind": "ERROR",
+ "position": "15",
+ "message": "test.js:1:15 Unclosed group near index 9\n([a-z])+(\n ^\n /([a-z])+(/;\n ^",
+ "lineNumber": "1"
+ },
+ {
+ "fileName": "test.js",
+ "code": "; (32, 1)",
+ "columnNumber": "15",
+ "kind": "ERROR",
+ "position": "32",
+ "message": "test.js:2:15 Unsupported RegExp flag: h\n /([a-z])+/h;\n ^",
+ "lineNumber": "2"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/dowhile.js Fri Mar 27 09:02:55 2015 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 continue tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+do {} while(false)
+do {break;} while(true)
+label:
+do {break label;} while(a == 2)
+do{do{}while(func1())}while(a + b > 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/dowhile.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -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"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/empty.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 = <<EOF
+
+;
+var a = 1;;
+1;
+
+EOF
+
+parse("empty.js", code, "--empty-statements", new (Java.extend(visitor, {
+ visitEmptyStatement : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/empty.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,12 @@
+[
+ {
+ "endPosition": "2",
+ "kind": "EMPTY_STATEMENT",
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "14",
+ "kind": "EMPTY_STATEMENT",
+ "startPosition": "13"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/erroneous.js Fri Mar 27 09:02:55 2015 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 erroneous tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+(1 + 2;
+x *;
+while;
+break;
+continue;
+
+EOF
+
+
+
+parse("erroneous.js", code, "-nse", new (Java.extend(visitor, {
+ visitErroneous : function (node, obj) {
+ obj.push(convert(node))
+ }
+})), function (message) {})
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/erroneous.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,27 @@
+[
+ {
+ "endPosition": "8",
+ "kind": "ERROR",
+ "startPosition": "7"
+ },
+ {
+ "endPosition": "13",
+ "kind": "ERROR",
+ "startPosition": "12"
+ },
+ {
+ "endPosition": "20",
+ "kind": "ERROR",
+ "startPosition": "19"
+ },
+ {
+ "endPosition": "27",
+ "kind": "ERROR",
+ "startPosition": "26"
+ },
+ {
+ "endPosition": "37",
+ "kind": "ERROR",
+ "startPosition": "36"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/for.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 for loop tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+for (i=0; someExpr;) {}
+for(;;){}
+for(var i=0; i < 4; i+=5) {}
+for(var i=0; i < 4; i++) {}
+for(i=0, j=2, x=4; x < 6; j++, x+=2, i*=x) {}
+
+EOF
+
+parse("forloop.js", code, "-nse", new (Java.extend(visitor, {
+ visitForLoop : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/for.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,281 @@
+[
+ {
+ "condition": {
+ "endPosition": "19",
+ "kind": "IDENTIFIER",
+ "name": "someExpr",
+ "startPosition": "11"
+ },
+ "endPosition": "24",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "24",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "22"
+ },
+ "update": "null",
+ "startPosition": "1",
+ "initializer": {
+ "expression": {
+ "endPosition": "9",
+ "kind": "NUMBER_LITERAL",
+ "value": "0",
+ "startPosition": "8"
+ },
+ "endPosition": "9",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "7",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "6"
+ },
+ "startPosition": "6"
+ }
+ },
+ {
+ "condition": "null",
+ "endPosition": "34",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "34",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "32"
+ },
+ "update": "null",
+ "startPosition": "25",
+ "initializer": "null"
+ },
+ {
+ "condition": {
+ "leftOperand": {
+ "endPosition": "49",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "48"
+ },
+ "endPosition": "53",
+ "kind": "LESS_THAN",
+ "rightOperand": {
+ "endPosition": "53",
+ "kind": "NUMBER_LITERAL",
+ "value": "4",
+ "startPosition": "52"
+ },
+ "startPosition": "48"
+ },
+ "endPosition": "63",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "63",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "61"
+ },
+ "update": {
+ "expression": {
+ "endPosition": "59",
+ "kind": "NUMBER_LITERAL",
+ "value": "5",
+ "startPosition": "58"
+ },
+ "endPosition": "59",
+ "kind": "PLUS_ASSIGNMENT",
+ "variable": {
+ "endPosition": "56",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "55"
+ },
+ "startPosition": "55"
+ },
+ "startPosition": "35",
+ "initializer": "null"
+ },
+ {
+ "condition": {
+ "leftOperand": {
+ "endPosition": "78",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "77"
+ },
+ "endPosition": "82",
+ "kind": "LESS_THAN",
+ "rightOperand": {
+ "endPosition": "82",
+ "kind": "NUMBER_LITERAL",
+ "value": "4",
+ "startPosition": "81"
+ },
+ "startPosition": "77"
+ },
+ "endPosition": "91",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "91",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "89"
+ },
+ "update": {
+ "expression": {
+ "endPosition": "85",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "84"
+ },
+ "endPosition": "87",
+ "kind": "POSTFIX_INCREMENT",
+ "startPosition": "84"
+ },
+ "startPosition": "64",
+ "initializer": "null"
+ },
+ {
+ "condition": {
+ "leftOperand": {
+ "endPosition": "112",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "111"
+ },
+ "endPosition": "116",
+ "kind": "LESS_THAN",
+ "rightOperand": {
+ "endPosition": "116",
+ "kind": "NUMBER_LITERAL",
+ "value": "6",
+ "startPosition": "115"
+ },
+ "startPosition": "111"
+ },
+ "endPosition": "137",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "137",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "135"
+ },
+ "update": {
+ "leftOperand": {
+ "leftOperand": {
+ "expression": {
+ "endPosition": "119",
+ "kind": "IDENTIFIER",
+ "name": "j",
+ "startPosition": "118"
+ },
+ "endPosition": "121",
+ "kind": "POSTFIX_INCREMENT",
+ "startPosition": "118"
+ },
+ "endPosition": "127",
+ "kind": "COMMA",
+ "rightOperand": {
+ "expression": {
+ "endPosition": "127",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "126"
+ },
+ "endPosition": "127",
+ "kind": "PLUS_ASSIGNMENT",
+ "variable": {
+ "endPosition": "124",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "123"
+ },
+ "startPosition": "123"
+ },
+ "startPosition": "118"
+ },
+ "endPosition": "133",
+ "kind": "COMMA",
+ "rightOperand": {
+ "expression": {
+ "endPosition": "133",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "132"
+ },
+ "endPosition": "133",
+ "kind": "MULTIPLY_ASSIGNMENT",
+ "variable": {
+ "endPosition": "130",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "129"
+ },
+ "startPosition": "129"
+ },
+ "startPosition": "118"
+ },
+ "startPosition": "92",
+ "initializer": {
+ "leftOperand": {
+ "leftOperand": {
+ "expression": {
+ "endPosition": "99",
+ "kind": "NUMBER_LITERAL",
+ "value": "0",
+ "startPosition": "98"
+ },
+ "endPosition": "99",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "97",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "96"
+ },
+ "startPosition": "96"
+ },
+ "endPosition": "104",
+ "kind": "COMMA",
+ "rightOperand": {
+ "expression": {
+ "endPosition": "104",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "103"
+ },
+ "endPosition": "104",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "102",
+ "kind": "IDENTIFIER",
+ "name": "j",
+ "startPosition": "101"
+ },
+ "startPosition": "101"
+ },
+ "startPosition": "96"
+ },
+ "endPosition": "109",
+ "kind": "COMMA",
+ "rightOperand": {
+ "expression": {
+ "endPosition": "109",
+ "kind": "NUMBER_LITERAL",
+ "value": "4",
+ "startPosition": "108"
+ },
+ "endPosition": "109",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "107",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "106"
+ },
+ "startPosition": "106"
+ },
+ "startPosition": "96"
+ }
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/forin.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,48 @@
+/*
+ * 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 for-in loop tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+for (i in obj) {}
+for (var i in obj) {}
+[].forEach(function(i, v){})
+
+EOF
+
+parse("forinloop.js", code, "-nse", new (Java.extend(visitor, {
+ visitForInLoop : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/forin.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,50 @@
+[
+ {
+ "expression": {
+ "endPosition": "14",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "11"
+ },
+ "endPosition": "18",
+ "kind": "FOR_IN_LOOP",
+ "forEach": "false",
+ "variable": {
+ "endPosition": "7",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "6"
+ },
+ "statement": {
+ "endPosition": "18",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "16"
+ },
+ "startPosition": "1"
+ },
+ {
+ "expression": {
+ "endPosition": "36",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "33"
+ },
+ "endPosition": "40",
+ "kind": "FOR_IN_LOOP",
+ "forEach": "false",
+ "variable": {
+ "endPosition": "29",
+ "kind": "IDENTIFIER",
+ "name": "i",
+ "startPosition": "28"
+ },
+ "statement": {
+ "endPosition": "40",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "38"
+ },
+ "startPosition": "19"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/functionCall.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 function call tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+func1()
+func2(a, b, c)
+func3(4, n * m);
+obj.call();
+obj.call(x, b());
+(function(){})();
+(function(){"use strict";})();
+(function(){})(2);
+(function(a, b){})(2);
+
+EOF
+
+parse("functionCall.js", code, "-nse", new (Java.extend(visitor, {
+ visitFunctionCall : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/functionCall.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,255 @@
+[
+ {
+ "endPosition": "8",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "6",
+ "kind": "IDENTIFIER",
+ "name": "func1",
+ "startPosition": "1"
+ },
+ "arguments": [],
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "23",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "14",
+ "kind": "IDENTIFIER",
+ "name": "func2",
+ "startPosition": "9"
+ },
+ "arguments": [
+ {
+ "endPosition": "16",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "15"
+ },
+ {
+ "endPosition": "19",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "18"
+ },
+ {
+ "endPosition": "22",
+ "kind": "IDENTIFIER",
+ "name": "c",
+ "startPosition": "21"
+ }
+ ],
+ "startPosition": "9"
+ },
+ {
+ "endPosition": "39",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "29",
+ "kind": "IDENTIFIER",
+ "name": "func3",
+ "startPosition": "24"
+ },
+ "arguments": [
+ {
+ "endPosition": "31",
+ "kind": "NUMBER_LITERAL",
+ "value": "4",
+ "startPosition": "30"
+ },
+ {
+ "leftOperand": {
+ "endPosition": "34",
+ "kind": "IDENTIFIER",
+ "name": "n",
+ "startPosition": "33"
+ },
+ "endPosition": "38",
+ "kind": "MULTIPLY",
+ "rightOperand": {
+ "endPosition": "38",
+ "kind": "IDENTIFIER",
+ "name": "m",
+ "startPosition": "37"
+ },
+ "startPosition": "33"
+ }
+ ],
+ "startPosition": "24"
+ },
+ {
+ "endPosition": "51",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "call",
+ "expression": {
+ "endPosition": "44",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "41"
+ },
+ "endPosition": "49",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "41"
+ },
+ "arguments": [],
+ "startPosition": "41"
+ },
+ {
+ "endPosition": "69",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "call",
+ "expression": {
+ "endPosition": "56",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "53"
+ },
+ "endPosition": "61",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "53"
+ },
+ "arguments": [
+ {
+ "endPosition": "63",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "62"
+ },
+ {
+ "endPosition": "68",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "66",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "65"
+ },
+ "arguments": [],
+ "startPosition": "65"
+ }
+ ],
+ "startPosition": "53"
+ },
+ {
+ "endPosition": "87",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "82",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "83",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "82"
+ },
+ "strict": "false",
+ "startPosition": "82",
+ "parameters": []
+ },
+ "arguments": [],
+ "startPosition": "71"
+ },
+ {
+ "endPosition": "118",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "100",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "114",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "112",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "102"
+ },
+ "endPosition": "112",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "102"
+ }
+ ],
+ "startPosition": "100"
+ },
+ "strict": "true",
+ "startPosition": "100",
+ "parameters": []
+ },
+ "arguments": [],
+ "startPosition": "89"
+ },
+ {
+ "endPosition": "137",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "131",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "132",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "131"
+ },
+ "strict": "false",
+ "startPosition": "131",
+ "parameters": []
+ },
+ "arguments": [
+ {
+ "endPosition": "136",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "135"
+ }
+ ],
+ "startPosition": "120"
+ },
+ {
+ "endPosition": "160",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "154",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "155",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "154"
+ },
+ "strict": "false",
+ "startPosition": "154",
+ "parameters": [
+ {
+ "endPosition": "150",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "149"
+ },
+ {
+ "endPosition": "153",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "152"
+ }
+ ]
+ },
+ "arguments": [
+ {
+ "endPosition": "159",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "158"
+ }
+ ],
+ "startPosition": "139"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/functionDeclaration.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,52 @@
+/*
+ * 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 function declaration tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+function a () {}
+function d(){
+ function e () {print(a)}
+}
+function f(a, b){print(a)}
+function j(a, b){"use strict";}
+
+EOF
+
+parse("functionDeclaration.js", code, "-nse", new (Java.extend(visitor, {
+ visitFunctionDeclaration : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/functionDeclaration.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,161 @@
+[
+ {
+ "endPosition": "17",
+ "kind": "FUNCTION",
+ "name": "a",
+ "body": {
+ "endPosition": "16",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "15"
+ },
+ "strict": "false",
+ "startPosition": "1",
+ "parameters": []
+ },
+ {
+ "endPosition": "62",
+ "kind": "FUNCTION",
+ "name": "d",
+ "body": {
+ "endPosition": "60",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "endPosition": "60",
+ "kind": "FUNCTION",
+ "name": "e",
+ "body": {
+ "endPosition": "59",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "59",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "56",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "51"
+ },
+ "arguments": [
+ {
+ "endPosition": "58",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "57"
+ }
+ ],
+ "startPosition": "51"
+ },
+ "endPosition": "59",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "51"
+ }
+ ],
+ "startPosition": "50"
+ },
+ "strict": "false",
+ "startPosition": "36",
+ "parameters": []
+ }
+ ],
+ "startPosition": "30"
+ },
+ "strict": "false",
+ "startPosition": "18",
+ "parameters": []
+ },
+ {
+ "endPosition": "89",
+ "kind": "FUNCTION",
+ "name": "f",
+ "body": {
+ "endPosition": "88",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "88",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "85",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "80"
+ },
+ "arguments": [
+ {
+ "endPosition": "87",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "86"
+ }
+ ],
+ "startPosition": "80"
+ },
+ "endPosition": "88",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "80"
+ }
+ ],
+ "startPosition": "79"
+ },
+ "strict": "false",
+ "startPosition": "63",
+ "parameters": [
+ {
+ "endPosition": "75",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "74"
+ },
+ {
+ "endPosition": "78",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "77"
+ }
+ ]
+ },
+ {
+ "endPosition": "121",
+ "kind": "FUNCTION",
+ "name": "j",
+ "body": {
+ "endPosition": "120",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "118",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "108"
+ },
+ "endPosition": "118",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "108"
+ }
+ ],
+ "startPosition": "106"
+ },
+ "strict": "true",
+ "startPosition": "90",
+ "parameters": [
+ {
+ "endPosition": "102",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "101"
+ },
+ {
+ "endPosition": "105",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "104"
+ }
+ ]
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/functionExpr.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,51 @@
+/*
+ * 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 function expression tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+var a = function () {}
+var b = function (x, y) {}
+var c = function (x, y) {"use strict"}
+var e = function () { return function (){"use strict"}}
+
+
+EOF
+
+parse("functionExpr.js", code, "-nse", new (Java.extend(visitor, {
+ visitFunctionExpression : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/functionExpr.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,128 @@
+[
+ {
+ "endPosition": "21",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "22",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "21"
+ },
+ "strict": "false",
+ "startPosition": "21",
+ "parameters": []
+ },
+ {
+ "endPosition": "48",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "49",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "48"
+ },
+ "strict": "false",
+ "startPosition": "48",
+ "parameters": [
+ {
+ "endPosition": "43",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "42"
+ },
+ {
+ "endPosition": "46",
+ "kind": "IDENTIFIER",
+ "name": "y",
+ "startPosition": "45"
+ }
+ ]
+ },
+ {
+ "endPosition": "75",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "87",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "87",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "77"
+ },
+ "endPosition": "87",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "77"
+ }
+ ],
+ "startPosition": "75"
+ },
+ "strict": "true",
+ "startPosition": "75",
+ "parameters": [
+ {
+ "endPosition": "70",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "69"
+ },
+ {
+ "endPosition": "73",
+ "kind": "IDENTIFIER",
+ "name": "y",
+ "startPosition": "72"
+ }
+ ]
+ },
+ {
+ "endPosition": "110",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "144",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "130",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "142",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "142",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "132"
+ },
+ "endPosition": "142",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "132"
+ }
+ ],
+ "startPosition": "130"
+ },
+ "strict": "true",
+ "startPosition": "130",
+ "parameters": []
+ },
+ "endPosition": "144",
+ "kind": "RETURN",
+ "startPosition": "112"
+ }
+ ],
+ "startPosition": "110"
+ },
+ "strict": "false",
+ "startPosition": "110",
+ "parameters": []
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/identifier.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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 identifier tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+undefined
+NaN
+a
+a23
+var_name
+_underscore
+$dollar
+
+EOF
+
+parse("identifier.js", code, "-nse", new (Java.extend(visitor, {
+ visitIdentifier : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/identifier.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,44 @@
+[
+ {
+ "endPosition": "10",
+ "kind": "IDENTIFIER",
+ "name": "undefined",
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "14",
+ "kind": "IDENTIFIER",
+ "name": "NaN",
+ "startPosition": "11"
+ },
+ {
+ "endPosition": "16",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "15"
+ },
+ {
+ "endPosition": "20",
+ "kind": "IDENTIFIER",
+ "name": "a23",
+ "startPosition": "17"
+ },
+ {
+ "endPosition": "29",
+ "kind": "IDENTIFIER",
+ "name": "var_name",
+ "startPosition": "21"
+ },
+ {
+ "endPosition": "41",
+ "kind": "IDENTIFIER",
+ "name": "_underscore",
+ "startPosition": "30"
+ },
+ {
+ "endPosition": "49",
+ "kind": "IDENTIFIER",
+ "name": "$dollar",
+ "startPosition": "42"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/if.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,52 @@
+/*
+ * 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 if-else tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+if (true) {}
+if (false) {}
+if (a) print(a)
+if ("STR") {}
+if ( a > 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))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/if.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -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"
+ }
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/instanceof.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 = <<EOF
+
+a instanceof Array
+a() instanceof Object
+1 instanceof a
+2 instanceof a()
+C.prototype instanceof Object
+"str" instanceof obj.member
+
+EOF
+
+parse("instanceof.js", code, "-nse", new (Java.extend(visitor, {
+ visitInstanceOf : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/instanceof.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,224 @@
+[
+ {
+ "leftOperand": {
+ "endPosition": "2",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "1"
+ },
+ "expression": {
+ "endPosition": "2",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "1"
+ },
+ "endPosition": "19",
+ "kind": "INSTANCE_OF",
+ "rightOperand": {
+ "endPosition": "19",
+ "kind": "IDENTIFIER",
+ "name": "Array",
+ "startPosition": "14"
+ },
+ "type": {
+ "endPosition": "19",
+ "kind": "IDENTIFIER",
+ "name": "Array",
+ "startPosition": "14"
+ },
+ "startPosition": "1"
+ },
+ {
+ "leftOperand": {
+ "endPosition": "23",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "21",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "20"
+ },
+ "arguments": [],
+ "startPosition": "20"
+ },
+ "expression": {
+ "endPosition": "23",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "21",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "20"
+ },
+ "arguments": [],
+ "startPosition": "20"
+ },
+ "endPosition": "41",
+ "kind": "INSTANCE_OF",
+ "rightOperand": {
+ "endPosition": "41",
+ "kind": "IDENTIFIER",
+ "name": "Object",
+ "startPosition": "35"
+ },
+ "type": {
+ "endPosition": "41",
+ "kind": "IDENTIFIER",
+ "name": "Object",
+ "startPosition": "35"
+ },
+ "startPosition": "20"
+ },
+ {
+ "leftOperand": {
+ "endPosition": "43",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "42"
+ },
+ "expression": {
+ "endPosition": "43",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "42"
+ },
+ "endPosition": "56",
+ "kind": "INSTANCE_OF",
+ "rightOperand": {
+ "endPosition": "56",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "55"
+ },
+ "type": {
+ "endPosition": "56",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "55"
+ },
+ "startPosition": "42"
+ },
+ {
+ "leftOperand": {
+ "endPosition": "58",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "57"
+ },
+ "expression": {
+ "endPosition": "58",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "57"
+ },
+ "endPosition": "73",
+ "kind": "INSTANCE_OF",
+ "rightOperand": {
+ "endPosition": "73",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "71",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "70"
+ },
+ "arguments": [],
+ "startPosition": "70"
+ },
+ "type": {
+ "endPosition": "73",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "71",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "70"
+ },
+ "arguments": [],
+ "startPosition": "70"
+ },
+ "startPosition": "57"
+ },
+ {
+ "leftOperand": {
+ "identifier": "prototype",
+ "expression": {
+ "endPosition": "75",
+ "kind": "IDENTIFIER",
+ "name": "C",
+ "startPosition": "74"
+ },
+ "endPosition": "85",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "74"
+ },
+ "expression": {
+ "identifier": "prototype",
+ "expression": {
+ "endPosition": "75",
+ "kind": "IDENTIFIER",
+ "name": "C",
+ "startPosition": "74"
+ },
+ "endPosition": "85",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "74"
+ },
+ "endPosition": "103",
+ "kind": "INSTANCE_OF",
+ "rightOperand": {
+ "endPosition": "103",
+ "kind": "IDENTIFIER",
+ "name": "Object",
+ "startPosition": "97"
+ },
+ "type": {
+ "endPosition": "103",
+ "kind": "IDENTIFIER",
+ "name": "Object",
+ "startPosition": "97"
+ },
+ "startPosition": "74"
+ },
+ {
+ "leftOperand": {
+ "endPosition": "108",
+ "kind": "STRING_LITERAL",
+ "value": "str",
+ "startPosition": "105"
+ },
+ "expression": {
+ "endPosition": "108",
+ "kind": "STRING_LITERAL",
+ "value": "str",
+ "startPosition": "105"
+ },
+ "endPosition": "131",
+ "kind": "INSTANCE_OF",
+ "rightOperand": {
+ "identifier": "member",
+ "expression": {
+ "endPosition": "124",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "121"
+ },
+ "endPosition": "131",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "121"
+ },
+ "type": {
+ "identifier": "member",
+ "expression": {
+ "endPosition": "124",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "121"
+ },
+ "endPosition": "131",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "121"
+ },
+ "startPosition": "105"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/labelledStat.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,52 @@
+/*
+ * 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 labeled statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+begin: { for (;;) break begin };
+begin: { while (true) break begin };
+begin: { while (false) continue begin };
+begin: { for (;;) continue begin };
+begin: { do continue begin; while(false);};
+begin: { do break begin; while(true);};
+
+EOF
+
+parse("labeledStat.js", code, "-nse", new (Java.extend(visitor, {
+ visitLabeledStatement : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/labelledStat.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,176 @@
+[
+ {
+ "endPosition": "32",
+ "kind": "LABELED_STATEMENT",
+ "statement": {
+ "endPosition": "32",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": "null",
+ "endPosition": "30",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "30",
+ "kind": "BREAK",
+ "label": "begin",
+ "startPosition": "19"
+ },
+ "update": "null",
+ "startPosition": "10",
+ "initializer": "null"
+ }
+ ],
+ "startPosition": "8"
+ },
+ "label": "begin",
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "69",
+ "kind": "LABELED_STATEMENT",
+ "statement": {
+ "endPosition": "69",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": {
+ "endPosition": "54",
+ "kind": "BOOLEAN_LITERAL",
+ "value": "true",
+ "startPosition": "50"
+ },
+ "endPosition": "67",
+ "kind": "WHILE_LOOP",
+ "statement": {
+ "endPosition": "67",
+ "kind": "BREAK",
+ "label": "begin",
+ "startPosition": "56"
+ },
+ "startPosition": "43"
+ }
+ ],
+ "startPosition": "41"
+ },
+ "label": "begin",
+ "startPosition": "34"
+ },
+ {
+ "endPosition": "110",
+ "kind": "LABELED_STATEMENT",
+ "statement": {
+ "endPosition": "110",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": {
+ "endPosition": "92",
+ "kind": "BOOLEAN_LITERAL",
+ "value": "false",
+ "startPosition": "87"
+ },
+ "endPosition": "108",
+ "kind": "WHILE_LOOP",
+ "statement": {
+ "endPosition": "108",
+ "kind": "CONTINUE",
+ "label": "begin",
+ "startPosition": "94"
+ },
+ "startPosition": "80"
+ }
+ ],
+ "startPosition": "78"
+ },
+ "label": "begin",
+ "startPosition": "71"
+ },
+ {
+ "endPosition": "146",
+ "kind": "LABELED_STATEMENT",
+ "statement": {
+ "endPosition": "146",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": "null",
+ "endPosition": "144",
+ "kind": "FOR_LOOP",
+ "statement": {
+ "endPosition": "144",
+ "kind": "CONTINUE",
+ "label": "begin",
+ "startPosition": "130"
+ },
+ "update": "null",
+ "startPosition": "121",
+ "initializer": "null"
+ }
+ ],
+ "startPosition": "119"
+ },
+ "label": "begin",
+ "startPosition": "112"
+ },
+ {
+ "endPosition": "190",
+ "kind": "LABELED_STATEMENT",
+ "statement": {
+ "endPosition": "190",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": {
+ "endPosition": "187",
+ "kind": "BOOLEAN_LITERAL",
+ "value": "false",
+ "startPosition": "182"
+ },
+ "endPosition": "189",
+ "kind": "DO_WHILE_LOOP",
+ "statement": {
+ "endPosition": "175",
+ "kind": "CONTINUE",
+ "label": "begin",
+ "startPosition": "160"
+ },
+ "startPosition": "157"
+ }
+ ],
+ "startPosition": "155"
+ },
+ "label": "begin",
+ "startPosition": "148"
+ },
+ {
+ "endPosition": "230",
+ "kind": "LABELED_STATEMENT",
+ "statement": {
+ "endPosition": "230",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "condition": {
+ "endPosition": "227",
+ "kind": "BOOLEAN_LITERAL",
+ "value": "true",
+ "startPosition": "223"
+ },
+ "endPosition": "229",
+ "kind": "DO_WHILE_LOOP",
+ "statement": {
+ "endPosition": "216",
+ "kind": "BREAK",
+ "label": "begin",
+ "startPosition": "204"
+ },
+ "startPosition": "201"
+ }
+ ],
+ "startPosition": "199"
+ },
+ "label": "begin",
+ "startPosition": "192"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/literal.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation literal statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+1
+null
+hello
+false
+"use strict";
+
+EOF
+
+parse("literal.js", code, "-nse", new (Java.extend(visitor, {
+ visitLiteral : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/literal.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,26 @@
+[
+ {
+ "endPosition": "2",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "7",
+ "kind": "NULL_LITERAL",
+ "value": "null",
+ "startPosition": "3"
+ },
+ {
+ "endPosition": "19",
+ "kind": "BOOLEAN_LITERAL",
+ "value": "false",
+ "startPosition": "14"
+ },
+ {
+ "endPosition": "31",
+ "kind": "STRING_LITERAL",
+ "value": "use strict",
+ "startPosition": "21"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/memberSelect.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 member select tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+object.field
+object.method()
+this.null
+Array.prototype
+
+EOF
+
+parse("memberSelect.js", code, "-nse", new (Java.extend(visitor, {
+ visitMemberSelect : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/memberSelect.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,50 @@
+[
+ {
+ "identifier": "field",
+ "expression": {
+ "endPosition": "7",
+ "kind": "IDENTIFIER",
+ "name": "object",
+ "startPosition": "1"
+ },
+ "endPosition": "13",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "1"
+ },
+ {
+ "identifier": "method",
+ "expression": {
+ "endPosition": "20",
+ "kind": "IDENTIFIER",
+ "name": "object",
+ "startPosition": "14"
+ },
+ "endPosition": "27",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "14"
+ },
+ {
+ "identifier": "null",
+ "expression": {
+ "endPosition": "34",
+ "kind": "IDENTIFIER",
+ "name": "this",
+ "startPosition": "30"
+ },
+ "endPosition": "39",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "30"
+ },
+ {
+ "identifier": "prototype",
+ "expression": {
+ "endPosition": "45",
+ "kind": "IDENTIFIER",
+ "name": "Array",
+ "startPosition": "40"
+ },
+ "endPosition": "55",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "40"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/new.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 new statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+new Object()
+new Array()
+new function (a,b,c) {}
+new func
+new obj.init
+
+EOF
+
+parse("new.js", code, "-nse", new (Java.extend(visitor, {
+ visitNew : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/new.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,120 @@
+[
+ {
+ "constructorExpression": {
+ "endPosition": "13",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "11",
+ "kind": "IDENTIFIER",
+ "name": "Object",
+ "startPosition": "5"
+ },
+ "arguments": [],
+ "startPosition": "5"
+ },
+ "endPosition": "13",
+ "kind": "NEW",
+ "startPosition": "1"
+ },
+ {
+ "constructorExpression": {
+ "endPosition": "25",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "23",
+ "kind": "IDENTIFIER",
+ "name": "Array",
+ "startPosition": "18"
+ },
+ "arguments": [],
+ "startPosition": "18"
+ },
+ "endPosition": "25",
+ "kind": "NEW",
+ "startPosition": "14"
+ },
+ {
+ "constructorExpression": {
+ "endPosition": "49",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "47",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "48",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "47"
+ },
+ "strict": "false",
+ "startPosition": "47",
+ "parameters": [
+ {
+ "endPosition": "41",
+ "kind": "IDENTIFIER",
+ "name": "a",
+ "startPosition": "40"
+ },
+ {
+ "endPosition": "43",
+ "kind": "IDENTIFIER",
+ "name": "b",
+ "startPosition": "42"
+ },
+ {
+ "endPosition": "45",
+ "kind": "IDENTIFIER",
+ "name": "c",
+ "startPosition": "44"
+ }
+ ]
+ },
+ "arguments": [],
+ "startPosition": "47"
+ },
+ "endPosition": "49",
+ "kind": "NEW",
+ "startPosition": "26"
+ },
+ {
+ "constructorExpression": {
+ "endPosition": "58",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "58",
+ "kind": "IDENTIFIER",
+ "name": "func",
+ "startPosition": "54"
+ },
+ "arguments": [],
+ "startPosition": "54"
+ },
+ "endPosition": "58",
+ "kind": "NEW",
+ "startPosition": "50"
+ },
+ {
+ "constructorExpression": {
+ "endPosition": "71",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "identifier": "init",
+ "expression": {
+ "endPosition": "66",
+ "kind": "IDENTIFIER",
+ "name": "obj",
+ "startPosition": "63"
+ },
+ "endPosition": "71",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "63"
+ },
+ "arguments": [],
+ "startPosition": "66"
+ },
+ "endPosition": "71",
+ "kind": "NEW",
+ "startPosition": "59"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js Fri Mar 27 09:02:55 2015 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 object literal tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+({ foo: 343 })
+obj = {};
+p = { x: 10, y: 2 };
+p = { 'x': 10, 'y': 2 };
+p = { get x() { return xValue }, get y() { return yValue } };
+p = { get foo() { return this._foo }, set foo(val) { this._foo = val } };
+
+
+EOF
+
+parse("objectLiteral.js", code, "-nse", new (Java.extend(visitor, {
+ visitObjectLiteral : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,310 @@
+[
+ {
+ "endPosition": "14",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "2",
+ "properties": [
+ {
+ "getter": "null",
+ "endPosition": "8",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "12",
+ "kind": "NUMBER_LITERAL",
+ "value": "343",
+ "startPosition": "9"
+ },
+ "startPosition": "4",
+ "key": {
+ "endPosition": "7",
+ "kind": "IDENTIFIER",
+ "name": "foo",
+ "startPosition": "4"
+ }
+ }
+ ]
+ },
+ {
+ "endPosition": "24",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "22",
+ "properties": []
+ },
+ {
+ "endPosition": "45",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "30",
+ "properties": [
+ {
+ "getter": "null",
+ "endPosition": "34",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "37",
+ "kind": "NUMBER_LITERAL",
+ "value": "10",
+ "startPosition": "35"
+ },
+ "startPosition": "32",
+ "key": {
+ "endPosition": "33",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "32"
+ }
+ },
+ {
+ "getter": "null",
+ "endPosition": "41",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "43",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "42"
+ },
+ "startPosition": "39",
+ "key": {
+ "endPosition": "40",
+ "kind": "IDENTIFIER",
+ "name": "y",
+ "startPosition": "39"
+ }
+ }
+ ]
+ },
+ {
+ "endPosition": "70",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "51",
+ "properties": [
+ {
+ "getter": "null",
+ "endPosition": "57",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "60",
+ "kind": "NUMBER_LITERAL",
+ "value": "10",
+ "startPosition": "58"
+ },
+ "startPosition": "54",
+ "key": {
+ "endPosition": "55",
+ "kind": "STRING_LITERAL",
+ "value": "x",
+ "startPosition": "54"
+ }
+ },
+ {
+ "getter": "null",
+ "endPosition": "66",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "68",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "67"
+ },
+ "startPosition": "63",
+ "key": {
+ "endPosition": "64",
+ "kind": "STRING_LITERAL",
+ "value": "y",
+ "startPosition": "63"
+ }
+ }
+ ]
+ },
+ {
+ "endPosition": "132",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "76",
+ "properties": [
+ {
+ "getter": {
+ "endPosition": "86",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "101",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "101",
+ "kind": "IDENTIFIER",
+ "name": "xValue",
+ "startPosition": "95"
+ },
+ "endPosition": "101",
+ "kind": "RETURN",
+ "startPosition": "88"
+ }
+ ],
+ "startPosition": "86"
+ },
+ "strict": "false",
+ "startPosition": "86",
+ "parameters": []
+ },
+ "endPosition": "103",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": "null",
+ "startPosition": "78",
+ "key": {
+ "endPosition": "83",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "82"
+ }
+ },
+ {
+ "getter": {
+ "endPosition": "113",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "128",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "128",
+ "kind": "IDENTIFIER",
+ "name": "yValue",
+ "startPosition": "122"
+ },
+ "endPosition": "128",
+ "kind": "RETURN",
+ "startPosition": "115"
+ }
+ ],
+ "startPosition": "113"
+ },
+ "strict": "false",
+ "startPosition": "113",
+ "parameters": []
+ },
+ "endPosition": "130",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": "null",
+ "startPosition": "105",
+ "key": {
+ "endPosition": "110",
+ "kind": "IDENTIFIER",
+ "name": "y",
+ "startPosition": "109"
+ }
+ }
+ ]
+ },
+ {
+ "endPosition": "206",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "138",
+ "properties": [
+ {
+ "getter": {
+ "endPosition": "150",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "168",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "identifier": "_foo",
+ "expression": {
+ "endPosition": "163",
+ "kind": "IDENTIFIER",
+ "name": "this",
+ "startPosition": "159"
+ },
+ "endPosition": "168",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "159"
+ },
+ "endPosition": "168",
+ "kind": "RETURN",
+ "startPosition": "152"
+ }
+ ],
+ "startPosition": "150"
+ },
+ "strict": "false",
+ "startPosition": "150",
+ "parameters": []
+ },
+ "endPosition": "170",
+ "kind": "PROPERTY",
+ "setter": {
+ "endPosition": "185",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "202",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "expression": {
+ "endPosition": "202",
+ "kind": "IDENTIFIER",
+ "name": "val",
+ "startPosition": "199"
+ },
+ "endPosition": "202",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "identifier": "_foo",
+ "expression": {
+ "endPosition": "191",
+ "kind": "IDENTIFIER",
+ "name": "this",
+ "startPosition": "187"
+ },
+ "endPosition": "196",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "187"
+ },
+ "startPosition": "187"
+ },
+ "endPosition": "202",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "187"
+ }
+ ],
+ "startPosition": "185"
+ },
+ "strict": "false",
+ "startPosition": "185",
+ "parameters": [
+ {
+ "endPosition": "183",
+ "kind": "IDENTIFIER",
+ "name": "val",
+ "startPosition": "180"
+ }
+ ]
+ },
+ "value": "null",
+ "startPosition": "140",
+ "key": {
+ "endPosition": "147",
+ "kind": "IDENTIFIER",
+ "name": "foo",
+ "startPosition": "144"
+ }
+ }
+ ]
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/property.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation property tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+var o = {
+ foo :'test',
+ _foo: call(),
+ $foo: function () {},
+ fo42: {}
+}
+
+EOF
+
+parse("property.js", code, "-nse", new (Java.extend(visitor, {
+ visitProperty : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,92 @@
+[
+ {
+ "getter": "null",
+ "endPosition": "17",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "22",
+ "kind": "STRING_LITERAL",
+ "value": "test",
+ "startPosition": "18"
+ },
+ "startPosition": "12",
+ "key": {
+ "endPosition": "15",
+ "kind": "IDENTIFIER",
+ "name": "foo",
+ "startPosition": "12"
+ }
+ },
+ {
+ "getter": "null",
+ "endPosition": "31",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "38",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "36",
+ "kind": "IDENTIFIER",
+ "name": "call",
+ "startPosition": "32"
+ },
+ "arguments": [],
+ "startPosition": "32"
+ },
+ "startPosition": "26",
+ "key": {
+ "endPosition": "30",
+ "kind": "IDENTIFIER",
+ "name": "_foo",
+ "startPosition": "26"
+ }
+ },
+ {
+ "getter": "null",
+ "endPosition": "46",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "59",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "60",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "59"
+ },
+ "strict": "false",
+ "startPosition": "59",
+ "parameters": []
+ },
+ "startPosition": "41",
+ "key": {
+ "endPosition": "45",
+ "kind": "IDENTIFIER",
+ "name": "$foo",
+ "startPosition": "41"
+ }
+ },
+ {
+ "getter": "null",
+ "endPosition": "69",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "72",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "70",
+ "properties": []
+ },
+ "startPosition": "64",
+ "key": {
+ "endPosition": "68",
+ "kind": "IDENTIFIER",
+ "name": "fo42",
+ "startPosition": "64"
+ }
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/regexp.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 regexp expression tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+/[abc]/i;
+/([^abc])*([a-z])+([^0-9])?(x|y)/ig.test();
+/^\w\W\n\f\0$/igm;
+
+EOF
+
+parse("regexp.js", code, "-nse", new (Java.extend(visitor, {
+ visitRegExpLiteral : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/regexp.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,23 @@
+[
+ {
+ "endPosition": "9",
+ "kind": "REGEXP_LITERAL",
+ "options": "i",
+ "pattern": "[abc]",
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "46",
+ "kind": "REGEXP_LITERAL",
+ "options": "ig",
+ "pattern": "([^abc])*([a-z])+([^0-9])?(x|y)",
+ "startPosition": "11"
+ },
+ {
+ "endPosition": "72",
+ "kind": "REGEXP_LITERAL",
+ "options": "igm",
+ "pattern": "^\\w\\W\\n\\f\\0$",
+ "startPosition": "55"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/return.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,65 @@
+/*
+ * 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 return expression tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+function a () {
+ return 1;
+}
+function b () {
+ return function () {
+ return {}
+ }
+}
+function c() {
+ for(;;) {
+ return;
+ }
+ return
+}
+
+function d () {
+ while(true) {
+ return
+ }
+}
+
+EOF
+
+parse("return.js", code, "-nse", new (Java.extend(visitor, {
+ visitReturn : function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/return.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,62 @@
+[
+ {
+ "expression": {
+ "endPosition": "29",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "28"
+ },
+ "endPosition": "30",
+ "kind": "RETURN",
+ "startPosition": "21"
+ },
+ {
+ "expression": {
+ "endPosition": "72",
+ "kind": "FUNCTION_EXPRESSION",
+ "name": "null",
+ "body": {
+ "endPosition": "91",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "91",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "89",
+ "properties": []
+ },
+ "endPosition": "91",
+ "kind": "RETURN",
+ "startPosition": "82"
+ }
+ ],
+ "startPosition": "72"
+ },
+ "strict": "false",
+ "startPosition": "72",
+ "parameters": []
+ },
+ "endPosition": "97",
+ "kind": "RETURN",
+ "startPosition": "53"
+ },
+ {
+ "expression": "null",
+ "endPosition": "144",
+ "kind": "RETURN",
+ "startPosition": "137"
+ },
+ {
+ "expression": "null",
+ "endPosition": "161",
+ "kind": "RETURN",
+ "startPosition": "155"
+ },
+ {
+ "expression": "null",
+ "endPosition": "213",
+ "kind": "RETURN",
+ "startPosition": "207"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/switch.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation switch statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+switch (key) {};
+switch (key) {
+ case 2: hello();
+ break;
+};
+switch (key) {
+ case 4: hello(); break;
+ case 2: world(); break;
+ default: break
+};
+
+EOF
+
+parse("switch.js", code, "-nse", new (Java.extend(visitor, {
+ visitSwitch: function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/switch.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,162 @@
+[
+ {
+ "cases": [],
+ "expression": {
+ "endPosition": "12",
+ "kind": "IDENTIFIER",
+ "name": "key",
+ "startPosition": "9"
+ },
+ "endPosition": "16",
+ "kind": "SWITCH",
+ "startPosition": "1"
+ },
+ {
+ "cases": [
+ {
+ "expression": {
+ "endPosition": "43",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "42"
+ },
+ "endPosition": "64",
+ "kind": "CASE",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "52",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "50",
+ "kind": "IDENTIFIER",
+ "name": "hello",
+ "startPosition": "45"
+ },
+ "arguments": [],
+ "startPosition": "45"
+ },
+ "endPosition": "52",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "45"
+ },
+ {
+ "endPosition": "64",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "58"
+ }
+ ],
+ "startPosition": "37"
+ }
+ ],
+ "expression": {
+ "endPosition": "29",
+ "kind": "IDENTIFIER",
+ "name": "key",
+ "startPosition": "26"
+ },
+ "endPosition": "66",
+ "kind": "SWITCH",
+ "startPosition": "18"
+ },
+ {
+ "cases": [
+ {
+ "expression": {
+ "endPosition": "93",
+ "kind": "NUMBER_LITERAL",
+ "value": "4",
+ "startPosition": "92"
+ },
+ "endPosition": "110",
+ "kind": "CASE",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "102",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "100",
+ "kind": "IDENTIFIER",
+ "name": "hello",
+ "startPosition": "95"
+ },
+ "arguments": [],
+ "startPosition": "95"
+ },
+ "endPosition": "102",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "95"
+ },
+ {
+ "endPosition": "110",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "104"
+ }
+ ],
+ "startPosition": "87"
+ },
+ {
+ "expression": {
+ "endPosition": "121",
+ "kind": "NUMBER_LITERAL",
+ "value": "2",
+ "startPosition": "120"
+ },
+ "endPosition": "138",
+ "kind": "CASE",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "130",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "128",
+ "kind": "IDENTIFIER",
+ "name": "world",
+ "startPosition": "123"
+ },
+ "arguments": [],
+ "startPosition": "123"
+ },
+ "endPosition": "130",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "123"
+ },
+ {
+ "endPosition": "138",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "132"
+ }
+ ],
+ "startPosition": "115"
+ },
+ {
+ "expression": "null",
+ "endPosition": "157",
+ "kind": "CASE",
+ "statements": [
+ {
+ "endPosition": "157",
+ "kind": "BREAK",
+ "label": "null",
+ "startPosition": "152"
+ }
+ ],
+ "startPosition": "143"
+ }
+ ],
+ "expression": {
+ "endPosition": "79",
+ "kind": "IDENTIFIER",
+ "name": "key",
+ "startPosition": "76"
+ },
+ "endPosition": "159",
+ "kind": "SWITCH",
+ "startPosition": "68"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/throw.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 throw statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+throw err;
+throw 'wrong';
+throw new TypeError;
+throw new TypeError('not an array');
+throw { msg: 'wrong!' };
+
+EOF
+
+parse("throw.js", code, "-nse", new (Java.extend(visitor, {
+ visitThrow: function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,106 @@
+[
+ {
+ "expression": {
+ "endPosition": "10",
+ "kind": "IDENTIFIER",
+ "name": "err",
+ "startPosition": "7"
+ },
+ "endPosition": "11",
+ "kind": "THROW",
+ "startPosition": "1"
+ },
+ {
+ "expression": {
+ "endPosition": "24",
+ "kind": "STRING_LITERAL",
+ "value": "wrong",
+ "startPosition": "19"
+ },
+ "endPosition": "26",
+ "kind": "THROW",
+ "startPosition": "12"
+ },
+ {
+ "expression": {
+ "constructorExpression": {
+ "endPosition": "46",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "46",
+ "kind": "IDENTIFIER",
+ "name": "TypeError",
+ "startPosition": "37"
+ },
+ "arguments": [],
+ "startPosition": "37"
+ },
+ "endPosition": "46",
+ "kind": "NEW",
+ "startPosition": "33"
+ },
+ "endPosition": "47",
+ "kind": "THROW",
+ "startPosition": "27"
+ },
+ {
+ "expression": {
+ "constructorExpression": {
+ "endPosition": "83",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "67",
+ "kind": "IDENTIFIER",
+ "name": "TypeError",
+ "startPosition": "58"
+ },
+ "arguments": [
+ {
+ "endPosition": "81",
+ "kind": "STRING_LITERAL",
+ "value": "not an array",
+ "startPosition": "69"
+ }
+ ],
+ "startPosition": "58"
+ },
+ "endPosition": "83",
+ "kind": "NEW",
+ "startPosition": "54"
+ },
+ "endPosition": "84",
+ "kind": "THROW",
+ "startPosition": "48"
+ },
+ {
+ "expression": {
+ "endPosition": "108",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "91",
+ "properties": [
+ {
+ "getter": "null",
+ "endPosition": "97",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "105",
+ "kind": "STRING_LITERAL",
+ "value": "wrong!",
+ "startPosition": "99"
+ },
+ "startPosition": "93",
+ "key": {
+ "endPosition": "96",
+ "kind": "IDENTIFIER",
+ "name": "msg",
+ "startPosition": "93"
+ }
+ }
+ ]
+ },
+ "endPosition": "109",
+ "kind": "THROW",
+ "startPosition": "85"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/try.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 try statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+try { } catch (e) { }
+try { } catch (e) { } finally {}
+try { } finally {}
+try { } catch (e) { handle() }
+try { that() } catch (e) { handle() } finally { clean() }
+
+EOF
+
+parse("throw.js", code, "-nse", new (Java.extend(visitor, {
+ visitTry: function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/try.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,230 @@
+[
+ {
+ "endPosition": "22",
+ "kind": "TRY",
+ "catches": [
+ {
+ "condition": "null",
+ "endPosition": "22",
+ "kind": "CATCH",
+ "parameter": {
+ "endPosition": "17",
+ "kind": "IDENTIFIER",
+ "name": "e",
+ "startPosition": "16"
+ },
+ "block": {
+ "endPosition": "22",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "19"
+ },
+ "startPosition": "9"
+ }
+ ],
+ "block": {
+ "endPosition": "8",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "5"
+ },
+ "finallyBlock": "null",
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "55",
+ "kind": "TRY",
+ "catches": [
+ {
+ "condition": "null",
+ "endPosition": "44",
+ "kind": "CATCH",
+ "parameter": {
+ "endPosition": "39",
+ "kind": "IDENTIFIER",
+ "name": "e",
+ "startPosition": "38"
+ },
+ "block": {
+ "endPosition": "44",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "41"
+ },
+ "startPosition": "31"
+ }
+ ],
+ "block": {
+ "endPosition": "30",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "27"
+ },
+ "finallyBlock": {
+ "endPosition": "55",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "53"
+ },
+ "startPosition": "23"
+ },
+ {
+ "endPosition": "74",
+ "kind": "TRY",
+ "catches": [],
+ "block": {
+ "endPosition": "63",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "60"
+ },
+ "finallyBlock": {
+ "endPosition": "74",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "72"
+ },
+ "startPosition": "56"
+ },
+ {
+ "endPosition": "105",
+ "kind": "TRY",
+ "catches": [
+ {
+ "condition": "null",
+ "endPosition": "105",
+ "kind": "CATCH",
+ "parameter": {
+ "endPosition": "91",
+ "kind": "IDENTIFIER",
+ "name": "e",
+ "startPosition": "90"
+ },
+ "block": {
+ "endPosition": "105",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "103",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "101",
+ "kind": "IDENTIFIER",
+ "name": "handle",
+ "startPosition": "95"
+ },
+ "arguments": [],
+ "startPosition": "95"
+ },
+ "endPosition": "103",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "95"
+ }
+ ],
+ "startPosition": "93"
+ },
+ "startPosition": "83"
+ }
+ ],
+ "block": {
+ "endPosition": "82",
+ "kind": "BLOCK",
+ "statements": [],
+ "startPosition": "79"
+ },
+ "finallyBlock": "null",
+ "startPosition": "75"
+ },
+ {
+ "endPosition": "163",
+ "kind": "TRY",
+ "catches": [
+ {
+ "condition": "null",
+ "endPosition": "143",
+ "kind": "CATCH",
+ "parameter": {
+ "endPosition": "129",
+ "kind": "IDENTIFIER",
+ "name": "e",
+ "startPosition": "128"
+ },
+ "block": {
+ "endPosition": "143",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "141",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "139",
+ "kind": "IDENTIFIER",
+ "name": "handle",
+ "startPosition": "133"
+ },
+ "arguments": [],
+ "startPosition": "133"
+ },
+ "endPosition": "141",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "133"
+ }
+ ],
+ "startPosition": "131"
+ },
+ "startPosition": "121"
+ }
+ ],
+ "block": {
+ "endPosition": "120",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "118",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "116",
+ "kind": "IDENTIFIER",
+ "name": "that",
+ "startPosition": "112"
+ },
+ "arguments": [],
+ "startPosition": "112"
+ },
+ "endPosition": "118",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "112"
+ }
+ ],
+ "startPosition": "110"
+ },
+ "finallyBlock": {
+ "endPosition": "163",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "endPosition": "161",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "159",
+ "kind": "IDENTIFIER",
+ "name": "clean",
+ "startPosition": "154"
+ },
+ "arguments": [],
+ "startPosition": "154"
+ },
+ "endPosition": "161",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "154"
+ }
+ ],
+ "startPosition": "152"
+ },
+ "startPosition": "106"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/unary.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,56 @@
+/*
+ * 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 unary expressions tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+x++;
+x--;
+delete x;
+void x;
+typeof x;
+++x;
+--x;
++x;
+-x;
+~x;
+!x;
+
+EOF
+
+parse("unary.js", code, "-nse", new (Java.extend(visitor, {
+ visitUnary: function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/unary.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,123 @@
+[
+ {
+ "expression": {
+ "endPosition": "2",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "1"
+ },
+ "endPosition": "4",
+ "kind": "POSTFIX_INCREMENT",
+ "startPosition": "1"
+ },
+ {
+ "expression": {
+ "endPosition": "7",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "6"
+ },
+ "endPosition": "9",
+ "kind": "POSTFIX_DECREMENT",
+ "startPosition": "6"
+ },
+ {
+ "expression": {
+ "endPosition": "19",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "18"
+ },
+ "endPosition": "19",
+ "kind": "DELETE",
+ "startPosition": "11"
+ },
+ {
+ "expression": {
+ "endPosition": "27",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "26"
+ },
+ "endPosition": "27",
+ "kind": "VOID",
+ "startPosition": "21"
+ },
+ {
+ "expression": {
+ "endPosition": "37",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "36"
+ },
+ "endPosition": "37",
+ "kind": "TYPEOF",
+ "startPosition": "29"
+ },
+ {
+ "expression": {
+ "endPosition": "42",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "41"
+ },
+ "endPosition": "42",
+ "kind": "PREFIX_INCREMENT",
+ "startPosition": "39"
+ },
+ {
+ "expression": {
+ "endPosition": "47",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "46"
+ },
+ "endPosition": "47",
+ "kind": "PREFIX_DECREMENT",
+ "startPosition": "44"
+ },
+ {
+ "expression": {
+ "endPosition": "51",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "50"
+ },
+ "endPosition": "51",
+ "kind": "PLUS",
+ "startPosition": "49"
+ },
+ {
+ "expression": {
+ "endPosition": "55",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "54"
+ },
+ "endPosition": "55",
+ "kind": "MINUS",
+ "startPosition": "53"
+ },
+ {
+ "expression": {
+ "endPosition": "59",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "58"
+ },
+ "endPosition": "59",
+ "kind": "BITWISE_COMPLEMENT",
+ "startPosition": "57"
+ },
+ {
+ "expression": {
+ "endPosition": "63",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "62"
+ },
+ "endPosition": "63",
+ "kind": "LOGICAL_COMPLEMENT",
+ "startPosition": "61"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/utils.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+/**
+ *
+ * @subtest
+ */
+
+var parser = Java.type('jdk.nashorn.api.tree.Parser');
+var tree = Java.type('jdk.nashorn.api.tree.Tree');
+var list = Java.type('java.util.List');
+var visitor = Java.type('jdk.nashorn.api.tree.SimpleTreeVisitorES5_1');
+var file = Java.type('java.io.File')
+var cls = Java.type('java.lang.Class')
+
+function convert (value) {
+ if (!value) {
+ return value;
+ }
+ var obj = Object.bindProperties({}, value)
+ var result = {}
+ for (var i in obj) {
+ var val = obj[i]
+ if (typeof(val) == 'object') {
+ if (val instanceof cls) {
+ continue;
+ }
+ if (val instanceof tree) {
+ result[i] = convert(val)
+ }
+ else if (val instanceof list) {
+ var lst = []
+ for (var j in val) {
+ lst.push(convert(val[j]))
+ }
+ result[i] = lst
+ }
+ else {
+ result[i] = String(val)
+ }
+ } else if (typeof(val) != 'function') {
+ result[i] = String(val)
+ }
+ }
+ return result
+}
+
+function parse(name, code, args, visitor, listener) {
+ var tree = parser.create(args).parse(name, code, listener || null)
+ var results = []
+ tree.accept(visitor, results)
+ print(JSON.stringify(results, null, 2))
+}
+
+
+function parseDiagnostic (code, args) {
+ var messages = new Array()
+ var tree = parser.create(args).parse("test.js", code, function (message) {
+ messages.push(convert(message))
+ })
+ print(JSON.stringify(messages, null, 2))
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/variable.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 variable statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+var a
+var x = 1
+var x23, $y = 1, _z
+
+EOF
+
+parse("variable.js", code, "-nse", new (Java.extend(visitor, {
+ visitVariable: function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/variable.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,47 @@
+[
+ {
+ "endPosition": "6",
+ "kind": "VARIABLE",
+ "name": "a",
+ "startPosition": "5",
+ "initializer": "null"
+ },
+ {
+ "endPosition": "16",
+ "kind": "VARIABLE",
+ "name": "x",
+ "startPosition": "11",
+ "initializer": {
+ "endPosition": "16",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "15"
+ }
+ },
+ {
+ "endPosition": "24",
+ "kind": "VARIABLE",
+ "name": "x23",
+ "startPosition": "21",
+ "initializer": "null"
+ },
+ {
+ "endPosition": "32",
+ "kind": "VARIABLE",
+ "name": "$y",
+ "startPosition": "26",
+ "initializer": {
+ "endPosition": "32",
+ "kind": "NUMBER_LITERAL",
+ "value": "1",
+ "startPosition": "31"
+ }
+ },
+ {
+ "endPosition": "36",
+ "kind": "VARIABLE",
+ "name": "_z",
+ "startPosition": "34",
+ "initializer": "null"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/while.js Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation while statement tree.
+ *
+ * @test
+ * @bug 8068306
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+
+var code = <<EOF
+
+while(true);
+while(false) {}
+while(2 > 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/while.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -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"
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/with.js Fri Mar 27 09:02:55 2015 +0100
@@ -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 = <<EOF
+
+with (scope) { x = y };
+with ({x:'test'}) print(x)
+with ({}) {
+ z = this.x
+}
+
+EOF
+
+parse("with.js", code, "-nse", new (Java.extend(visitor, {
+ visitWith: function (node, obj) {
+ obj.push(convert(node))
+ }
+})))
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED Fri Mar 27 09:02:55 2015 +0100
@@ -0,0 +1,143 @@
+[
+ {
+ "endPosition": "23",
+ "kind": "WITH",
+ "scope": {
+ "endPosition": "12",
+ "kind": "IDENTIFIER",
+ "name": "scope",
+ "startPosition": "7"
+ },
+ "statement": {
+ "endPosition": "23",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "expression": {
+ "endPosition": "21",
+ "kind": "IDENTIFIER",
+ "name": "y",
+ "startPosition": "20"
+ },
+ "endPosition": "21",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "17",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "16"
+ },
+ "startPosition": "16"
+ },
+ "endPosition": "21",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "16"
+ }
+ ],
+ "startPosition": "14"
+ },
+ "startPosition": "1"
+ },
+ {
+ "endPosition": "51",
+ "kind": "WITH",
+ "scope": {
+ "endPosition": "41",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "31",
+ "properties": [
+ {
+ "getter": "null",
+ "endPosition": "34",
+ "kind": "PROPERTY",
+ "setter": "null",
+ "value": {
+ "endPosition": "39",
+ "kind": "STRING_LITERAL",
+ "value": "test",
+ "startPosition": "35"
+ },
+ "startPosition": "32",
+ "key": {
+ "endPosition": "33",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "32"
+ }
+ }
+ ]
+ },
+ "statement": {
+ "expression": {
+ "endPosition": "51",
+ "kind": "FUNCTION_INVOCATION",
+ "functionSelect": {
+ "endPosition": "48",
+ "kind": "IDENTIFIER",
+ "name": "print",
+ "startPosition": "43"
+ },
+ "arguments": [
+ {
+ "endPosition": "50",
+ "kind": "IDENTIFIER",
+ "name": "x",
+ "startPosition": "49"
+ }
+ ],
+ "startPosition": "43"
+ },
+ "endPosition": "51",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "43"
+ },
+ "startPosition": "25"
+ },
+ {
+ "endPosition": "80",
+ "kind": "WITH",
+ "scope": {
+ "endPosition": "60",
+ "kind": "OBJECT_LITERAL",
+ "startPosition": "58",
+ "properties": []
+ },
+ "statement": {
+ "endPosition": "80",
+ "kind": "BLOCK",
+ "statements": [
+ {
+ "expression": {
+ "expression": {
+ "identifier": "x",
+ "expression": {
+ "endPosition": "76",
+ "kind": "IDENTIFIER",
+ "name": "this",
+ "startPosition": "72"
+ },
+ "endPosition": "78",
+ "kind": "MEMBER_SELECT",
+ "startPosition": "72"
+ },
+ "endPosition": "78",
+ "kind": "ASSIGNMENT",
+ "variable": {
+ "endPosition": "69",
+ "kind": "IDENTIFIER",
+ "name": "z",
+ "startPosition": "68"
+ },
+ "startPosition": "68"
+ },
+ "endPosition": "78",
+ "kind": "EXPRESSION_STATEMENT",
+ "startPosition": "68"
+ }
+ ],
+ "startPosition": "62"
+ },
+ "startPosition": "52"
+ }
+]
--- a/test/lib/sun/hotspot/WhiteBox.java Fri Mar 20 11:42:31 2015 -0700
+++ b/test/lib/sun/hotspot/WhiteBox.java Fri Mar 27 09:02:55 2015 +0100
@@ -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
@@ -27,6 +27,7 @@
import java.lang.reflect.Executable;
import java.util.Arrays;
import java.util.List;
+import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;
import java.security.BasicPermission;
@@ -250,6 +251,23 @@
}
return offset;
}
+ public native Boolean getMethodBooleanOption(Executable method, String name);
+ public native Long getMethodIntxOption(Executable method, String name);
+ public native Long getMethodUintxOption(Executable method, String name);
+ public native Double getMethodDoubleOption(Executable method, String name);
+ public native String getMethodStringOption(Executable method, String name);
+ private final List<BiFunction<Executable,String,Object>> 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);