# HG changeset patch # User prr # Date 1428341743 25200 # Node ID 427f83353f732c86e3944866b64b7821428f06d9 # Parent d47c58140b41739a5dbb70889e13934e99d3e20f# Parent 1d3f0325164595b0b919d53b00f77d0de72b734f Merge diff -r d47c58140b41 -r 427f83353f73 .hgtags --- a/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -298,3 +298,5 @@ 874d76e4699dfcd61ae1826c9fe0ddc1610ad598 jdk9-b53 82cd31c5d6ca8d4c1653f4eb1c09eb2d9a3b2813 jdk9-b54 c97e2d1bad9708d379793ba2a4c848eda14c741e jdk9-b55 +47544495db2d3d2edf0f85862d8715592fdb919f jdk9-b56 +ddb95d8f169b09544cc17e72a6baaff2400092f5 jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 .hgtags-top-repo --- a/.hgtags-top-repo Tue Mar 31 16:22:59 2015 -0700 +++ b/.hgtags-top-repo Mon Apr 06 10:35:43 2015 -0700 @@ -298,3 +298,5 @@ d6ed47125a76cd1cf8a100568507bfb5e9669d9f jdk9-b53 cb7367141e910e265b8344a8facee740bd1e5467 jdk9-b54 0c37a832458f0e0b7d2a3f1a6f69aeae311aeb18 jdk9-b55 +eb7febe45865ba6b81f2ea68082262d0708a0b22 jdk9-b56 +f25ee9f62427a9ba27418e5531a89754791a305b jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 README-builds.html --- a/README-builds.html Tue Mar 31 16:22:59 2015 -0700 +++ b/README-builds.html Mon Apr 06 10:35:43 2015 -0700 @@ -441,7 +441,7 @@
  • Install - Visual Studio 2010 + Visual Studio 2013
  • @@ -750,23 +750,23 @@ -
    Visual Studio 2010 Compilers
    +
    Visual Studio 2013 Compilers

    The 32-bit and 64-bit OpenJDK Windows build requires - Microsoft Visual Studio C++ 2010 (VS2010) Professional + Microsoft Visual Studio C++ 2013 (VS2013) Professional Edition or Express compiler. The compiler and other tools are expected to reside in the location defined by the variable - VS100COMNTOOLS which + VS120COMNTOOLS which is set by the Microsoft Visual Studio installer.

    - Only the C++ part of VS2010 is needed. + Only the C++ part of VS2013 is needed. Try to let the installation go to the default install directory. - Always reboot your system after installing VS2010. - The system environment variable VS100COMNTOOLS + Always reboot your system after installing VS2013. + The system environment variable VS120COMNTOOLS should be set in your environment.

    @@ -1040,7 +1040,7 @@
    This is usually picked up automatically from the redist - directories of Visual Studio 2010. + directories of Visual Studio 2013. @@ -1854,54 +1854,54 @@ Linux X86 (32-bit) and X64 (64-bit) - Fedora 9 - gcc 4.3 - JDK 7u7 + Oracle Enterprise Linux 6.4 + gcc 4.8.2 + JDK 8 2 or more 1 GB 6 GB - Solaris SPARC (32-bit) and SPARCV9 (64-bit) - Solaris 10 Update 6 - Studio 12 Update 1 + patches - JDK 7u7 + Solaris SPARCV9 (64-bit) + Solaris 10 Update 10 + Studio 12 Update 3 + patches + JDK 8 4 or more 4 GB 8 GB - Solaris X86 (32-bit) and X64 (64-bit) - Solaris 10 Update 6 - Studio 12 Update 1 + patches - JDK 7u7 + Solaris X64 (64-bit) + Solaris 10 Update 10 + Studio 12 Update 3 + patches + JDK 8 4 or more 4 GB 8 GB Windows X86 (32-bit) - Windows XP - Microsoft Visual Studio C++ 2010 Professional Edition - JDK 7u7 + Windows Server 2012 R2 x64 + Microsoft Visual Studio C++ 2013 Professional Edition + JDK 8 2 or more 2 GB 6 GB Windows X64 (64-bit) - Windows Server 2003 - Enterprise x64 Edition - Microsoft Visual Studio C++ 2010 Professional Edition - JDK 7u7 + Windows Server 2012 R2 x64 + Microsoft Visual Studio C++ 2013 Professional Edition + JDK 8 2 or more 2 GB 6 GB Mac OS X X64 (64-bit) - Mac OS X 10.7 "Lion" - XCode 4.5.2 or newer - JDK 7u7 + Mac OS X 10.9 "Mavericks" + XCode 5.1.1 or newer + JDK 8 2 or more 4 GB 6 GB @@ -2009,7 +2009,7 @@

    Ubuntu 12.04

    -
    +
    After installing Ubuntu 12.04 you need to install several build dependencies. The simplest way to do it is to execute the following commands: diff -r d47c58140b41 -r 427f83353f73 common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Tue Mar 31 16:22:59 2015 -0700 +++ b/common/autoconf/generated-configure.sh Mon Apr 06 10:35:43 2015 -0700 @@ -4290,8 +4290,8 @@ # ################################################################################ - -VALID_VS_VERSIONS="2010 2012 2013" +# The order of these defines the priority by which we try to find them. +VALID_VS_VERSIONS="2013 2012 2010" VS_DESCRIPTION_2010="Microsoft Visual Studio 2010" VS_VERSION_INTERNAL_2010=100 @@ -4365,7 +4365,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1427843803 +DATE_WHEN_GENERATED=1428017006 ############################################################################### # diff -r d47c58140b41 -r 427f83353f73 common/autoconf/toolchain_windows.m4 --- a/common/autoconf/toolchain_windows.m4 Tue Mar 31 16:22:59 2015 -0700 +++ b/common/autoconf/toolchain_windows.m4 Mon Apr 06 10:35:43 2015 -0700 @@ -24,8 +24,8 @@ # ################################################################################ - -VALID_VS_VERSIONS="2010 2012 2013" +# The order of these defines the priority by which we try to find them. +VALID_VS_VERSIONS="2013 2012 2010" VS_DESCRIPTION_2010="Microsoft Visual Studio 2010" VS_VERSION_INTERNAL_2010=100 @@ -72,7 +72,7 @@ else VCVARSFILE="vc/bin/amd64/vcvars64.bat" fi - + BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(VS_BASE) if test -d "$VS_BASE"; then if test -f "$VS_BASE/$VCVARSFILE"; then @@ -404,7 +404,7 @@ METHOD="$3" if test -n "$POSSIBLE_MSVC_DLL" -a -e "$POSSIBLE_MSVC_DLL"; then AC_MSG_NOTICE([Found $1 at $POSSIBLE_MSVC_DLL using $METHOD]) - + # Need to check if the found msvcr is correct architecture AC_MSG_CHECKING([found $1 architecture]) MSVC_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVC_DLL"` @@ -463,9 +463,9 @@ TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL([$DLL_NAME], [$POSSIBLE_MSVC_DLL], [well-known location in Boot JDK]) fi - + if test "x$MSVC_DLL" = x; then - # Probe: Look in the Windows system32 directory + # Probe: Look in the Windows system32 directory CYGWIN_SYSTEMROOT="$SYSTEMROOT" BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(CYGWIN_SYSTEMROOT) POSSIBLE_MSVC_DLL="$CYGWIN_SYSTEMROOT/system32/$DLL_NAME" @@ -489,7 +489,7 @@ [search of VS100COMNTOOLS]) fi fi - + if test "x$MSVC_DLL" = x; then # Probe: Search wildly in the VCINSTALLDIR. We've probably lost by now. # (This was the original behaviour; kept since it might turn something up) @@ -506,12 +506,12 @@ | $HEAD --lines 1` fi fi - + TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL([$DLL_NAME], [$POSSIBLE_MSVC_DLL], [search of VCINSTALLDIR]) fi fi - + if test "x$MSVC_DLL" = x; then AC_MSG_CHECKING([for $DLL_NAME]) AC_MSG_RESULT([no]) diff -r d47c58140b41 -r 427f83353f73 corba/.hgtags --- a/corba/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/corba/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -298,3 +298,5 @@ aadc16ca5ab7d56f92ef9dbfa443595a939241b4 jdk9-b53 d469c5ad0c763e325a78e0af3016878a57dfc5cc jdk9-b54 734ca5311a225711b79618f3e92f47f07c82154a jdk9-b55 +ef4afd6832b00b8687832c2a36c90e43750ebe40 jdk9-b56 +d8ebf1a5b18ccbc849f5bf0f80aa3d78583eee68 jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 hotspot/.hgtags --- a/hotspot/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -458,3 +458,5 @@ effd5ef0c3eb4bb85aa975c489d6761dbf13ad6a jdk9-b53 c3b117fa5bdedfafd9ed236403e6d406911195b1 jdk9-b54 be49ab55e5c498c5077bbf58c2737100d1992339 jdk9-b55 +fd2d5ec7e7b16c7bf4043a7fe7cfd8af96b819e2 jdk9-b56 +56a85ffe743d3f9d70ba25d6ce82ddd2ad1bf33c jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -63,10 +63,6 @@ // Entry frames private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; - // Native frames - private static int NATIVE_FRAME_INITIAL_PARAM_OFFSET; - - static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -76,10 +72,8 @@ } private static synchronized void initialize(TypeDataBase db) { - int abi_minframe_size = db.lookupIntConstant("frame::abi_minframe_size").intValue(); int entry_frame_locals_size = db.lookupIntConstant("frame::entry_frame_locals_size").intValue(); int wordLength = (int) VM.getVM().getAddressSize(); - NATIVE_FRAME_INITIAL_PARAM_OFFSET = -abi_minframe_size/wordLength; ENTRY_FRAME_CALL_WRAPPER_OFFSET = -entry_frame_locals_size/wordLength; } @@ -389,13 +383,6 @@ // Return address: public Address getSenderPC() { return getSenderSP().getAddressAt(2 * VM.getVM().getAddressSize()); } - // return address of param, zero origin index. - // MPJ note: Appears to be unused. - public Address getNativeParamAddr(int idx) { - return null; - // return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx); - } - public Address getSenderSP() { return getFP(); } public Address addressOfInterpreterFrameLocals() { return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); diff -r d47c58140b41 -r 427f83353f73 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -63,9 +63,6 @@ // Entry frames private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; - // Native frames - private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; - private static VMReg rbp; static { @@ -423,20 +420,12 @@ return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); } - // FIXME: not implementable yet - //inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } - public Address getUnextendedSP() { return raw_unextendedSP; } // Return address: public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } - // return address of param, zero origin index. - public Address getNativeParamAddr(int idx) { - return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx); - } - public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } public Address addressOfInterpreterFrameLocals() { diff -r d47c58140b41 -r 427f83353f73 hotspot/make/linux/Makefile --- a/hotspot/make/linux/Makefile Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/make/linux/Makefile Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -233,7 +233,7 @@ # Solaris 2.5.1, 2.6). # Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok. -SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 3% +SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 3% 4% OS_VERSION := $(shell uname -r) EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION)) diff -r d47c58140b41 -r 427f83353f73 hotspot/make/linux/makefiles/gcc.make --- a/hotspot/make/linux/makefiles/gcc.make Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/make/linux/makefiles/gcc.make Mon Apr 06 10:35:43 2015 -0700 @@ -214,6 +214,11 @@ # conversions which might affect the values. Only enable it in earlier versions. ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" WARNING_FLAGS += -Wconversion + endif + ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1" + # This flag is only known since GCC 4.3. Gcc 4.8 contains a fix so that with templates no + # warnings are issued: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856 + WARNING_FLAGS += -Wtype-limits endif endif diff -r d47c58140b41 -r 427f83353f73 hotspot/make/windows/makefiles/projectcreator.make --- a/hotspot/make/windows/makefiles/projectcreator.make Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/make/windows/makefiles/projectcreator.make Mon Apr 06 10:35:43 2015 -0700 @@ -69,6 +69,7 @@ -ignorePath ppc \ -ignorePath zero \ -ignorePath aix \ + -ignorePath aarch64 \ -hidePath .hg diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/aarch64/vm/aarch64.ad --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Apr 06 10:35:43 2015 -0700 @@ -3735,12 +3735,12 @@ interface(CONST_INTER); %} -// constant 'double +0.0'. +// Double Immediate: +0.0d operand immD0() %{ - predicate((n->getd() == 0) && - (fpclassify(n->getd()) == FP_ZERO) && (signbit(n->getd()) == 0)); + predicate(jlong_cast(n->getd()) == 0); match(ConD); + op_cost(0); format %{ %} interface(CONST_INTER); @@ -3765,12 +3765,12 @@ interface(CONST_INTER); %} -// constant 'float +0.0'. +// Float Immediate: +0.0f. operand immF0() %{ - predicate((n->getf() == 0) && - (fpclassify(n->getf()) == FP_ZERO) && (signbit(n->getf()) == 0)); + predicate(jint_cast(n->getf()) == 0); match(ConF); + op_cost(0); format %{ %} interface(CONST_INTER); @@ -6056,7 +6056,7 @@ %} // Store Byte -instruct storeB_volatile(iRegI src, /* sync_memory*/indirect mem) +instruct storeB_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) %{ match(Set mem (StoreB mem src)); @@ -6069,7 +6069,7 @@ %} // Store Char/Short -instruct storeC_volatile(iRegI src, /* sync_memory*/indirect mem) +instruct storeC_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) %{ match(Set mem (StoreC mem src)); @@ -6225,7 +6225,7 @@ // ============================================================================ // Zero Count Instructions -instruct countLeadingZerosI(iRegINoSp dst, iRegI src) %{ +instruct countLeadingZerosI(iRegINoSp dst, iRegIorL2I src) %{ match(Set dst (CountLeadingZerosI src)); ins_cost(INSN_COST); @@ -6249,7 +6249,7 @@ ins_pipe(ialu_reg); %} -instruct countTrailingZerosI(iRegINoSp dst, iRegI src) %{ +instruct countTrailingZerosI(iRegINoSp dst, iRegIorL2I src) %{ match(Set dst (CountTrailingZerosI src)); ins_cost(INSN_COST * 2); @@ -6935,7 +6935,7 @@ // which throws a ShouldNotHappen. So, we have to provide two flavours // of each rule, one for a cmpOp and a second for a cmpOpU (sigh). -instruct cmovI_reg_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegI src1, iRegI src2) %{ +instruct cmovI_reg_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ match(Set dst (CMoveI (Binary cmp cr) (Binary src1 src2))); ins_cost(INSN_COST * 2); @@ -6951,7 +6951,7 @@ ins_pipe(icond_reg_reg); %} -instruct cmovUI_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegI src1, iRegI src2) %{ +instruct cmovUI_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ match(Set dst (CMoveI (Binary cmp cr) (Binary src1 src2))); ins_cost(INSN_COST * 2); @@ -6976,7 +6976,7 @@ // we ought only to be able to cull one of these variants as the ideal // transforms ought always to order the zero consistently (to left/right?) -instruct cmovI_zero_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, immI0 zero, iRegI src) %{ +instruct cmovI_zero_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, immI0 zero, iRegIorL2I src) %{ match(Set dst (CMoveI (Binary cmp cr) (Binary zero src))); ins_cost(INSN_COST * 2); @@ -6992,7 +6992,7 @@ ins_pipe(icond_reg); %} -instruct cmovUI_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, immI0 zero, iRegI src) %{ +instruct cmovUI_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, immI0 zero, iRegIorL2I src) %{ match(Set dst (CMoveI (Binary cmp cr) (Binary zero src))); ins_cost(INSN_COST * 2); @@ -7008,7 +7008,7 @@ ins_pipe(icond_reg); %} -instruct cmovI_reg_zero(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegI src, immI0 zero) %{ +instruct cmovI_reg_zero(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegIorL2I src, immI0 zero) %{ match(Set dst (CMoveI (Binary cmp cr) (Binary src zero))); ins_cost(INSN_COST * 2); @@ -7024,7 +7024,7 @@ ins_pipe(icond_reg); %} -instruct cmovUI_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegI src, immI0 zero) %{ +instruct cmovUI_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegIorL2I src, immI0 zero) %{ match(Set dst (CMoveI (Binary cmp cr) (Binary src zero))); ins_cost(INSN_COST * 2); @@ -7476,7 +7476,7 @@ ins_pipe(ialu_reg_reg); %} -instruct addI_reg_imm(iRegINoSp dst, iRegI src1, immIAddSub src2) %{ +instruct addI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immIAddSub src2) %{ match(Set dst (AddI src1 src2)); ins_cost(INSN_COST); @@ -7869,7 +7869,7 @@ ins_pipe(idiv_reg_reg); %} -instruct signExtract(iRegINoSp dst, iRegI src1, immI_31 div1, immI_31 div2) %{ +instruct signExtract(iRegINoSp dst, iRegIorL2I src1, immI_31 div1, immI_31 div2) %{ match(Set dst (URShiftI (RShiftI src1 div1) div2)); ins_cost(INSN_COST); format %{ "lsrw $dst, $src1, $div1" %} @@ -7879,7 +7879,7 @@ ins_pipe(ialu_reg_shift); %} -instruct div2Round(iRegINoSp dst, iRegI src, immI_31 div1, immI_31 div2) %{ +instruct div2Round(iRegINoSp dst, iRegIorL2I src, immI_31 div1, immI_31 div2) %{ match(Set dst (AddI src (URShiftI (RShiftI src div1) div2))); ins_cost(INSN_COST); format %{ "addw $dst, $src, LSR $div1" %} @@ -8189,7 +8189,7 @@ ins_pipe(ialu_reg); %} instruct regI_not_reg(iRegINoSp dst, - iRegI src1, immI_M1 m1, + iRegIorL2I src1, immI_M1 m1, rFlagsReg cr) %{ match(Set dst (XorI src1 m1)); ins_cost(INSN_COST); @@ -8206,14 +8206,14 @@ %} instruct AndI_reg_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, immI_M1 m1, + iRegIorL2I src1, iRegIorL2I src2, immI_M1 m1, rFlagsReg cr) %{ match(Set dst (AndI src1 (XorI src2 m1))); ins_cost(INSN_COST); - format %{ "bic $dst, $src1, $src2" %} - - ins_encode %{ - __ bic(as_Register($dst$$reg), + format %{ "bicw $dst, $src1, $src2" %} + + ins_encode %{ + __ bicw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg), Assembler::LSL, 0); @@ -8240,14 +8240,14 @@ %} instruct OrI_reg_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, immI_M1 m1, + iRegIorL2I src1, iRegIorL2I src2, immI_M1 m1, rFlagsReg cr) %{ match(Set dst (OrI src1 (XorI src2 m1))); ins_cost(INSN_COST); - format %{ "orn $dst, $src1, $src2" %} - - ins_encode %{ - __ orn(as_Register($dst$$reg), + format %{ "ornw $dst, $src1, $src2" %} + + ins_encode %{ + __ ornw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg), Assembler::LSL, 0); @@ -8274,14 +8274,14 @@ %} instruct XorI_reg_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, immI_M1 m1, + iRegIorL2I src1, iRegIorL2I src2, immI_M1 m1, rFlagsReg cr) %{ match(Set dst (XorI m1 (XorI src2 src1))); ins_cost(INSN_COST); - format %{ "eon $dst, $src1, $src2" %} - - ins_encode %{ - __ eon(as_Register($dst$$reg), + format %{ "eonw $dst, $src1, $src2" %} + + ins_encode %{ + __ eonw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg), Assembler::LSL, 0); @@ -8308,7 +8308,7 @@ %} instruct AndI_reg_URShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (AndI src1 (XorI(URShiftI src2 src3) src4))); ins_cost(1.9 * INSN_COST); @@ -8344,7 +8344,7 @@ %} instruct AndI_reg_RShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (AndI src1 (XorI(RShiftI src2 src3) src4))); ins_cost(1.9 * INSN_COST); @@ -8380,7 +8380,7 @@ %} instruct AndI_reg_LShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (AndI src1 (XorI(LShiftI src2 src3) src4))); ins_cost(1.9 * INSN_COST); @@ -8416,7 +8416,7 @@ %} instruct XorI_reg_URShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (XorI src4 (XorI(URShiftI src2 src3) src1))); ins_cost(1.9 * INSN_COST); @@ -8452,7 +8452,7 @@ %} instruct XorI_reg_RShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (XorI src4 (XorI(RShiftI src2 src3) src1))); ins_cost(1.9 * INSN_COST); @@ -8488,7 +8488,7 @@ %} instruct XorI_reg_LShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (XorI src4 (XorI(LShiftI src2 src3) src1))); ins_cost(1.9 * INSN_COST); @@ -8524,7 +8524,7 @@ %} instruct OrI_reg_URShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (OrI src1 (XorI(URShiftI src2 src3) src4))); ins_cost(1.9 * INSN_COST); @@ -8560,7 +8560,7 @@ %} instruct OrI_reg_RShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (OrI src1 (XorI(RShiftI src2 src3) src4))); ins_cost(1.9 * INSN_COST); @@ -8596,7 +8596,7 @@ %} instruct OrI_reg_LShift_not_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, immI_M1 src4, rFlagsReg cr) %{ match(Set dst (OrI src1 (XorI(LShiftI src2 src3) src4))); ins_cost(1.9 * INSN_COST); @@ -8632,7 +8632,7 @@ %} instruct AndI_reg_URShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (AndI src1 (URShiftI src2 src3))); @@ -8670,7 +8670,7 @@ %} instruct AndI_reg_RShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (AndI src1 (RShiftI src2 src3))); @@ -8708,7 +8708,7 @@ %} instruct AndI_reg_LShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (AndI src1 (LShiftI src2 src3))); @@ -8746,7 +8746,7 @@ %} instruct XorI_reg_URShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (XorI src1 (URShiftI src2 src3))); @@ -8784,7 +8784,7 @@ %} instruct XorI_reg_RShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (XorI src1 (RShiftI src2 src3))); @@ -8822,7 +8822,7 @@ %} instruct XorI_reg_LShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (XorI src1 (LShiftI src2 src3))); @@ -8860,7 +8860,7 @@ %} instruct OrI_reg_URShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (OrI src1 (URShiftI src2 src3))); @@ -8898,7 +8898,7 @@ %} instruct OrI_reg_RShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (OrI src1 (RShiftI src2 src3))); @@ -8936,7 +8936,7 @@ %} instruct OrI_reg_LShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (OrI src1 (LShiftI src2 src3))); @@ -8974,7 +8974,7 @@ %} instruct AddI_reg_URShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (AddI src1 (URShiftI src2 src3))); @@ -9012,7 +9012,7 @@ %} instruct AddI_reg_RShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (AddI src1 (RShiftI src2 src3))); @@ -9050,7 +9050,7 @@ %} instruct AddI_reg_LShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (AddI src1 (LShiftI src2 src3))); @@ -9088,7 +9088,7 @@ %} instruct SubI_reg_URShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (SubI src1 (URShiftI src2 src3))); @@ -9126,7 +9126,7 @@ %} instruct SubI_reg_RShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (SubI src1 (RShiftI src2 src3))); @@ -9164,7 +9164,7 @@ %} instruct SubI_reg_LShift_reg(iRegINoSp dst, - iRegI src1, iRegI src2, + iRegIorL2I src1, iRegIorL2I src2, immI src3, rFlagsReg cr) %{ match(Set dst (SubI src1 (LShiftI src2 src3))); @@ -9228,7 +9228,7 @@ // Shift Left followed by Shift Right. // This idiom is used by the compiler for the i2b bytecode etc. -instruct sbfmwI(iRegINoSp dst, iRegI src, immI lshift_count, immI rshift_count) +instruct sbfmwI(iRegINoSp dst, iRegIorL2I src, immI lshift_count, immI rshift_count) %{ match(Set dst (RShiftI (LShiftI src lshift_count) rshift_count)); // Make sure we are not going to exceed what sbfmw can do. @@ -9274,7 +9274,7 @@ // Shift Left followed by Shift Right. // This idiom is used by the compiler for the i2b bytecode etc. -instruct ubfmwI(iRegINoSp dst, iRegI src, immI lshift_count, immI rshift_count) +instruct ubfmwI(iRegINoSp dst, iRegIorL2I src, immI lshift_count, immI rshift_count) %{ match(Set dst (URShiftI (LShiftI src lshift_count) rshift_count)); // Make sure we are not going to exceed what ubfmw can do. @@ -9296,7 +9296,7 @@ %} // Bitfield extract with shift & mask -instruct ubfxwI(iRegINoSp dst, iRegI src, immI rshift, immI_bitmask mask) +instruct ubfxwI(iRegINoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask) %{ match(Set dst (AndI (URShiftI src rshift) mask)); @@ -9362,7 +9362,7 @@ ins_pipe(ialu_reg_reg_extr); %} -instruct extrOrI(iRegINoSp dst, iRegI src1, iRegI src2, immI lshift, immI rshift, rFlagsReg cr) +instruct extrOrI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst (OrI (LShiftI src1 lshift) (URShiftI src2 rshift))); predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31)); @@ -9392,7 +9392,7 @@ ins_pipe(ialu_reg_reg_extr); %} -instruct extrAddI(iRegINoSp dst, iRegI src1, iRegI src2, immI lshift, immI rshift, rFlagsReg cr) +instruct extrAddI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst (AddI (LShiftI src1 lshift) (URShiftI src2 rshift))); predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31)); @@ -9571,7 +9571,7 @@ %}; -instruct AddExtI_sxth(iRegINoSp dst, iRegI src1, iRegI src2, immI_16 lshift, immI_16 rshift, rFlagsReg cr) +instruct AddExtI_sxth(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_16 lshift, immI_16 rshift, rFlagsReg cr) %{ match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift))); ins_cost(INSN_COST); @@ -9584,7 +9584,7 @@ ins_pipe(ialu_reg_reg); %} -instruct AddExtI_sxtb(iRegINoSp dst, iRegI src1, iRegI src2, immI_24 lshift, immI_24 rshift, rFlagsReg cr) +instruct AddExtI_sxtb(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_24 lshift, immI_24 rshift, rFlagsReg cr) %{ match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift))); ins_cost(INSN_COST); @@ -9597,7 +9597,7 @@ ins_pipe(ialu_reg_reg); %} -instruct AddExtI_uxtb(iRegINoSp dst, iRegI src1, iRegI src2, immI_24 lshift, immI_24 rshift, rFlagsReg cr) +instruct AddExtI_uxtb(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_24 lshift, immI_24 rshift, rFlagsReg cr) %{ match(Set dst (AddI src1 (URShiftI (LShiftI src2 lshift) rshift))); ins_cost(INSN_COST); @@ -9663,7 +9663,7 @@ %} -instruct AddExtI_uxtb_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_255 mask, rFlagsReg cr) +instruct AddExtI_uxtb_and(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_255 mask, rFlagsReg cr) %{ match(Set dst (AddI src1 (AndI src2 mask))); ins_cost(INSN_COST); @@ -9676,7 +9676,7 @@ ins_pipe(ialu_reg_reg); %} -instruct AddExtI_uxth_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_65535 mask, rFlagsReg cr) +instruct AddExtI_uxth_and(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_65535 mask, rFlagsReg cr) %{ match(Set dst (AddI src1 (AndI src2 mask))); ins_cost(INSN_COST); @@ -9728,7 +9728,7 @@ ins_pipe(ialu_reg_reg); %} -instruct SubExtI_uxtb_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_255 mask, rFlagsReg cr) +instruct SubExtI_uxtb_and(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_255 mask, rFlagsReg cr) %{ match(Set dst (SubI src1 (AndI src2 mask))); ins_cost(INSN_COST); @@ -9741,7 +9741,7 @@ ins_pipe(ialu_reg_reg); %} -instruct SubExtI_uxth_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_65535 mask, rFlagsReg cr) +instruct SubExtI_uxth_and(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_65535 mask, rFlagsReg cr) %{ match(Set dst (SubI src1 (AndI src2 mask))); ins_cost(INSN_COST); @@ -10343,7 +10343,7 @@ %} // this pattern occurs in bigmath arithmetic -instruct convUI2L_reg_reg(iRegLNoSp dst, iRegI src, immL_32bits mask) +instruct convUI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{ match(Set dst (AndL (ConvI2L src) mask)); @@ -10369,7 +10369,7 @@ ins_pipe(ialu_reg); %} -instruct convI2B(iRegINoSp dst, iRegI src, rFlagsReg cr) +instruct convI2B(iRegINoSp dst, iRegIorL2I src, rFlagsReg cr) %{ match(Set dst (Conv2B src)); effect(KILL cr); @@ -10457,7 +10457,7 @@ ins_pipe(pipe_class_default); %} -instruct convI2F_reg_reg(vRegF dst, iRegI src) %{ +instruct convI2F_reg_reg(vRegF dst, iRegIorL2I src) %{ match(Set dst (ConvI2F src)); ins_cost(INSN_COST * 5); @@ -10509,7 +10509,7 @@ ins_pipe(pipe_class_default); %} -instruct convI2D_reg_reg(vRegD dst, iRegI src) %{ +instruct convI2D_reg_reg(vRegD dst, iRegIorL2I src) %{ match(Set dst (ConvI2D src)); ins_cost(INSN_COST * 5); @@ -10772,7 +10772,7 @@ // ============================================================================ // Overflow Math Instructions -instruct overflowAddI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2) +instruct overflowAddI_reg_reg(rFlagsReg cr, iRegIorL2I op1, iRegIorL2I op2) %{ match(Set cr (OverflowAddI op1 op2)); @@ -10785,7 +10785,7 @@ ins_pipe(icmp_reg_reg); %} -instruct overflowAddI_reg_imm(rFlagsReg cr, iRegI op1, immIAddSub op2) +instruct overflowAddI_reg_imm(rFlagsReg cr, iRegIorL2I op1, immIAddSub op2) %{ match(Set cr (OverflowAddI op1 op2)); @@ -10824,7 +10824,7 @@ ins_pipe(icmp_reg_imm); %} -instruct overflowSubI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2) +instruct overflowSubI_reg_reg(rFlagsReg cr, iRegIorL2I op1, iRegIorL2I op2) %{ match(Set cr (OverflowSubI op1 op2)); @@ -10837,7 +10837,7 @@ ins_pipe(icmp_reg_reg); %} -instruct overflowSubI_reg_imm(rFlagsReg cr, iRegI op1, immIAddSub op2) +instruct overflowSubI_reg_imm(rFlagsReg cr, iRegIorL2I op1, immIAddSub op2) %{ match(Set cr (OverflowSubI op1 op2)); @@ -10876,7 +10876,7 @@ ins_pipe(icmp_reg_imm); %} -instruct overflowNegI_reg(rFlagsReg cr, immI0 zero, iRegI op1) +instruct overflowNegI_reg(rFlagsReg cr, immI0 zero, iRegIorL2I op1) %{ match(Set cr (OverflowSubI zero op1)); @@ -10902,7 +10902,7 @@ ins_pipe(icmp_reg_imm); %} -instruct overflowMulI_reg(rFlagsReg cr, iRegI op1, iRegI op2) +instruct overflowMulI_reg(rFlagsReg cr, iRegIorL2I op1, iRegIorL2I op2) %{ match(Set cr (OverflowMulI op1 op2)); @@ -10923,7 +10923,7 @@ ins_pipe(pipe_slow); %} -instruct overflowMulI_reg_branch(cmpOp cmp, iRegI op1, iRegI op2, label labl, rFlagsReg cr) +instruct overflowMulI_reg_branch(cmpOp cmp, iRegIorL2I op1, iRegIorL2I op2, label labl, rFlagsReg cr) %{ match(If cmp (OverflowMulI op1 op2)); predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow @@ -11393,7 +11393,7 @@ %} -instruct cmpLTMask_reg_reg(iRegINoSp dst, iRegI p, iRegI q, rFlagsReg cr) +instruct cmpLTMask_reg_reg(iRegINoSp dst, iRegIorL2I p, iRegIorL2I q, rFlagsReg cr) %{ match(Set dst (CmpLTMask p q)); effect(KILL cr); @@ -11414,7 +11414,7 @@ ins_pipe(ialu_reg_reg); %} -instruct cmpLTMask_reg_zero(iRegINoSp dst, iRegI src, immI0 zero, rFlagsReg cr) +instruct cmpLTMask_reg_zero(iRegINoSp dst, iRegIorL2I src, immI0 zero, rFlagsReg cr) %{ match(Set dst (CmpLTMask src zero)); effect(KILL cr); @@ -11548,7 +11548,7 @@ // shorter than (cmp; branch), have the additional benefit of not // killing the flags. -instruct cmpI_imm0_branch(cmpOp cmp, iRegI op1, immI0 op2, label labl, rFlagsReg cr) %{ +instruct cmpI_imm0_branch(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsReg cr) %{ match(If cmp (CmpI op1 op2)); predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne || n->in(1)->as_Bool()->_test._test == BoolTest::eq); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 --- a/hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 Mon Apr 06 10:35:43 2015 -0700 @@ -24,11 +24,13 @@ dnl and shift patterns patterns used in aarch64.ad. dnl // BEGIN This section of the file is automatically generated. Do not edit -------------- - +dnl +define(`ORL2I', `ifelse($1,I,orL2I)') +dnl define(`BASE_SHIFT_INSN', ` instruct $2$1_reg_$4_reg(iReg$1NoSp dst, - iReg$1 src1, iReg$1 src2, + iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immI src3, rFlagsReg cr) %{ match(Set dst ($2$1 src1 ($4$1 src2 src3))); @@ -48,7 +50,7 @@ define(`BASE_INVERTED_INSN', ` instruct $2$1_reg_not_reg(iReg$1NoSp dst, - iReg$1 src1, iReg$1 src2, imm$1_M1 m1, + iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, imm$1_M1 m1, rFlagsReg cr) %{ dnl This ifelse is because hotspot reassociates (xor (xor ..)..) dnl into this canonical form. @@ -70,7 +72,7 @@ define(`INVERTED_SHIFT_INSN', ` instruct $2$1_reg_$4_not_reg(iReg$1NoSp dst, - iReg$1 src1, iReg$1 src2, + iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immI src3, imm$1_M1 src4, rFlagsReg cr) %{ dnl This ifelse is because hotspot reassociates (xor (xor ..)..) dnl into this canonical form. @@ -92,7 +94,7 @@ %}')dnl define(`NOT_INSN', `instruct reg$1_not_reg(iReg$1NoSp dst, - iReg$1 src1, imm$1_M1 m1, + iReg$1`'ORL2I($1) src1, imm$1_M1 m1, rFlagsReg cr) %{ match(Set dst (Xor$1 src1 m1)); ins_cost(INSN_COST); @@ -113,7 +115,7 @@ BASE_SHIFT_INSN(L, $1, $2, $3, $4)')dnl dnl define(`BOTH_INVERTED_INSNS', -`BASE_INVERTED_INSN(I, $1, $2, $3, $4) +`BASE_INVERTED_INSN(I, $1, $2w, $3, $4) BASE_INVERTED_INSN(L, $1, $2, $3, $4)')dnl dnl define(`BOTH_INVERTED_SHIFT_INSNS', @@ -149,7 +151,7 @@ define(`BFM_INSN',` // Shift Left followed by Shift Right. // This idiom is used by the compiler for the i2b bytecode etc. -instruct $4$1(iReg$1NoSp dst, iReg$1 src, immI lshift_count, immI rshift_count) +instruct $4$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI lshift_count, immI rshift_count) %{ match(Set dst EXTEND($1, $3, src, lshift_count, rshift_count)); // Make sure we are not going to exceed what $4 can do. @@ -176,7 +178,7 @@ dnl // Bitfield extract with shift & mask define(`BFX_INSN', -`instruct $3$1(iReg$1NoSp dst, iReg$1 src, immI rshift, imm$1_bitmask mask) +`instruct $3$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI rshift, imm$1_bitmask mask) %{ match(Set dst (And$1 ($2$1 src rshift) mask)); @@ -215,7 +217,7 @@ // Rotations define(`EXTRACT_INSN', -`instruct extr$3$1(iReg$1NoSp dst, iReg$1 src1, iReg$1 src2, immI lshift, immI rshift, rFlagsReg cr) +`instruct extr$3$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst ($3$1 (LShift$1 src1 lshift) (URShift$1 src2 rshift))); predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & $2)); @@ -299,7 +301,7 @@ // Add/subtract (extended) dnl ADD_SUB_EXTENDED(mode, size, add node, shift node, insn, shift type, wordsize define(`ADD_SUB_CONV', ` -instruct $3Ext$1(iReg$2NoSp dst, iReg$2 src1, iReg$1orL2I src2, rFlagsReg cr) +instruct $3Ext$1(iReg$2NoSp dst, iReg$2`'ORL2I($2) src1, iReg$1`'ORL2I($1) src2, rFlagsReg cr) %{ match(Set dst ($3$2 src1 (ConvI2L src2))); ins_cost(INSN_COST); @@ -315,7 +317,7 @@ ADD_SUB_CONV(I,L,Sub,sub,sxtw); dnl define(`ADD_SUB_EXTENDED', ` -instruct $3Ext$1_$6(iReg$1NoSp dst, iReg$1 src1, iReg$1 src2, immI_`'eval($7-$2) lshift, immI_`'eval($7-$2) rshift, rFlagsReg cr) +instruct $3Ext$1_$6(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immI_`'eval($7-$2) lshift, immI_`'eval($7-$2) rshift, rFlagsReg cr) %{ match(Set dst ($3$1 src1 EXTEND($1, $4, src2, lshift, rshift))); ins_cost(INSN_COST); @@ -337,7 +339,7 @@ dnl dnl ADD_SUB_ZERO_EXTEND(mode, size, add node, insn, shift type) define(`ADD_SUB_ZERO_EXTEND', ` -instruct $3Ext$1_$5_and(iReg$1NoSp dst, iReg$1 src1, iReg$1 src2, imm$1_$2 mask, rFlagsReg cr) +instruct $3Ext$1_$5_and(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, imm$1_$2 mask, rFlagsReg cr) %{ match(Set dst ($3$1 src1 (And$1 src2 mask))); ins_cost(INSN_COST); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -136,12 +136,7 @@ entry_frame_call_wrapper_offset = -8, // we don't need a save area - arg_reg_save_area_bytes = 0, - - // TODO - check that this is still correct - // Native frames - - native_frame_initial_param_offset = 2 + arg_reg_save_area_bytes = 0 }; @@ -195,9 +190,6 @@ inline address* sender_pc_addr() const; - // return address of param, zero origin index. - inline address* native_param_addr(int idx) const; - // expression stack tos if we are nested in a java call intptr_t* interpreter_frame_last_sp() const; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp --- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -166,7 +166,6 @@ inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } -inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } @@ -176,9 +175,6 @@ inline address* frame::sender_pc_addr() const { return (address*) addr_at( return_addr_offset); } inline address frame::sender_pc() const { return *sender_pc_addr(); } -// return address of param, zero origin index. -inline address* frame::native_param_addr(int idx) const { return (address*) addr_at( native_frame_initial_param_offset+idx); } - #ifdef CC_INTERP inline interpreterState frame::get_interpreterState() const { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Mon Apr 06 10:35:43 2015 -0700 @@ -4416,11 +4416,11 @@ interface(CONST_INTER); %} -// constant 'float +0.0'. +// Float Immediate: +0.0f. operand immF_0() %{ - predicate((n->getf() == 0) && - (fpclassify(n->getf()) == FP_ZERO) && (signbit(n->getf()) == 0)); + predicate(jint_cast(n->getf()) == 0); match(ConF); + op_cost(0); format %{ %} interface(CONST_INTER); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp --- a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -69,8 +69,6 @@ inline intptr_t* frame::link() const { return (intptr_t *)(fp()[FP->sp_offset_in_saved_window()] + STACK_BIAS); } -inline void frame::set_link(intptr_t* addr) { assert(link()==addr, "frame nesting is controlled by hardware"); } - inline intptr_t* frame::unextended_sp() const { return sp() + _sp_adjustment_by_callee; } // return address: diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Mon Apr 06 10:35:43 2015 -0700 @@ -3758,13 +3758,9 @@ interface(CONST_INTER); %} +// Double Immediate: +0.0d operand immD0() %{ -#ifdef _LP64 - // on 64-bit architectures this comparision is faster predicate(jlong_cast(n->getd()) == 0); -#else - predicate((n->getd() == 0) && (fpclass(n->getd()) == FP_PZERO)); -#endif match(ConD); op_cost(0); @@ -3781,9 +3777,9 @@ interface(CONST_INTER); %} -// Float Immediate: 0 +// Float Immediate: +0.0f operand immF0() %{ - predicate((n->getf() == 0) && (fpclass(n->getf()) == FP_PZERO)); + predicate(jint_cast(n->getf()) == 0); match(ConF); op_cost(0); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/frame_x86.hpp --- a/hotspot/src/cpu/x86/vm/frame_x86.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -128,21 +128,16 @@ entry_frame_after_call_words = 28, entry_frame_call_wrapper_offset = 2, - arg_reg_save_area_bytes = 32, // Register argument save area + arg_reg_save_area_bytes = 32 // Register argument save area #else entry_frame_after_call_words = 13, entry_frame_call_wrapper_offset = -6, - arg_reg_save_area_bytes = 0, + arg_reg_save_area_bytes = 0 #endif // _WIN64 #else - entry_frame_call_wrapper_offset = 2, + entry_frame_call_wrapper_offset = 2 #endif // AMD64 - - // Native frames - - native_frame_initial_param_offset = 2 - }; intptr_t ptr_at(int offset) const { @@ -195,9 +190,6 @@ inline address* sender_pc_addr() const; - // return address of param, zero origin index. - inline address* native_param_addr(int idx) const; - // expression stack tos if we are nested in a java call intptr_t* interpreter_frame_last_sp() const; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/frame_x86.inline.hpp --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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,8 +139,6 @@ inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } -inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } - inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } @@ -149,9 +147,6 @@ inline address* frame::sender_pc_addr() const { return (address*) addr_at( return_addr_offset); } inline address frame::sender_pc() const { return *sender_pc_addr(); } -// return address of param, zero origin index. -inline address* frame::native_param_addr(int idx) const { return (address*) addr_at( native_frame_initial_param_offset+idx); } - #ifdef CC_INTERP inline interpreterState frame::get_interpreterState() const { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/interp_masm_x86.cpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -25,7 +25,20 @@ #include "precompiled.hpp" #include "interp_masm_x86.hpp" #include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "oops/arrayOop.hpp" +#include "oops/markOop.hpp" #include "oops/methodData.hpp" +#include "oops/method.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiRedefineClassesTrace.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/basicLock.hpp" +#include "runtime/biasedLocking.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.inline.hpp" + +// Implementation of InterpreterMacroAssembler #ifndef CC_INTERP void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) { @@ -227,3 +240,1637 @@ } } #endif + +#ifdef CC_INTERP +void InterpreterMacroAssembler::get_method(Register reg) { + movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); + movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); +} +#endif // CC_INTERP + +#ifndef CC_INTERP +void InterpreterMacroAssembler::call_VM_leaf_base(address entry_point, + int number_of_arguments) { + // interpreter specific + // + // Note: No need to save/restore bcp & locals registers + // since these are callee saved registers and no blocking/ + // GC can happen in leaf calls. + // Further Note: DO NOT save/restore bcp/locals. If a caller has + // already saved them so that it can use rsi/rdi as temporaries + // then a save/restore here will DESTROY the copy the caller + // saved! There used to be a save_bcp() that only happened in + // the ASSERT path (no restore_bcp). Which caused bizarre failures + // when jvm built with ASSERTs. +#ifdef ASSERT + { + Label L; + cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + jcc(Assembler::equal, L); + stop("InterpreterMacroAssembler::call_VM_leaf_base:" + " last_sp != NULL"); + bind(L); + } +#endif + // super call + MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); + // interpreter specific + // LP64: Used to ASSERT that r13/r14 were equal to frame's bcp/locals + // but since they may not have been saved (and we don't want to + // save them here (see note above) the assert is invalid. +} + +void InterpreterMacroAssembler::call_VM_base(Register oop_result, + Register java_thread, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + // interpreter specific + // + // Note: Could avoid restoring locals ptr (callee saved) - however doesn't + // really make a difference for these runtime calls, since they are + // slow anyway. Btw., bcp must be saved/restored since it may change + // due to GC. + NOT_LP64(assert(java_thread == noreg , "not expecting a precomputed java thread");) + save_bcp(); +#ifdef ASSERT + { + Label L; + cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + jcc(Assembler::equal, L); + stop("InterpreterMacroAssembler::call_VM_leaf_base:" + " last_sp != NULL"); + bind(L); + } +#endif /* ASSERT */ + // super call + MacroAssembler::call_VM_base(oop_result, noreg, last_java_sp, + entry_point, number_of_arguments, + check_exceptions); + // interpreter specific + restore_bcp(); + restore_locals(); +} + +void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { + if (JvmtiExport::can_pop_frame()) { + Label L; + // Initiate popframe handling only if it is not already being + // processed. If the flag has the popframe_processing bit set, it + // means that this code is called *during* popframe handling - we + // don't want to reenter. + // This method is only called just after the call into the vm in + // call_VM_base, so the arg registers are available. + Register pop_cond = NOT_LP64(java_thread) // Not clear if any other register is available on 32 bit + LP64_ONLY(c_rarg0); + movl(pop_cond, Address(java_thread, JavaThread::popframe_condition_offset())); + testl(pop_cond, JavaThread::popframe_pending_bit); + jcc(Assembler::zero, L); + testl(pop_cond, JavaThread::popframe_processing_bit); + jcc(Assembler::notZero, L); + // Call Interpreter::remove_activation_preserving_args_entry() to get the + // address of the same-named entrypoint in the generated interpreter code. + call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); + jmp(rax); + bind(L); + NOT_LP64(get_thread(java_thread);) + } +} + +void InterpreterMacroAssembler::load_earlyret_value(TosState state) { + Register thread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + NOT_LP64(get_thread(thread);) + movptr(rcx, Address(thread, JavaThread::jvmti_thread_state_offset())); + const Address tos_addr(rcx, JvmtiThreadState::earlyret_tos_offset()); + const Address oop_addr(rcx, JvmtiThreadState::earlyret_oop_offset()); + const Address val_addr(rcx, JvmtiThreadState::earlyret_value_offset()); +#ifdef _LP64 + switch (state) { + case atos: movptr(rax, oop_addr); + movptr(oop_addr, (int32_t)NULL_WORD); + verify_oop(rax, state); break; + case ltos: movptr(rax, val_addr); break; + case btos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: movl(rax, val_addr); break; + case ftos: movflt(xmm0, val_addr); break; + case dtos: movdbl(xmm0, val_addr); break; + case vtos: /* nothing to do */ break; + default : ShouldNotReachHere(); + } + // Clean up tos value in the thread object + movl(tos_addr, (int) ilgl); + movl(val_addr, (int32_t) NULL_WORD); +#else + const Address val_addr1(rcx, JvmtiThreadState::earlyret_value_offset() + + in_ByteSize(wordSize)); + switch (state) { + case atos: movptr(rax, oop_addr); + movptr(oop_addr, NULL_WORD); + verify_oop(rax, state); break; + case ltos: + movl(rdx, val_addr1); // fall through + case btos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: movl(rax, val_addr); break; + case ftos: fld_s(val_addr); break; + case dtos: fld_d(val_addr); break; + case vtos: /* nothing to do */ break; + default : ShouldNotReachHere(); + } +#endif // _LP64 + // Clean up tos value in the thread object + movl(tos_addr, (int32_t) ilgl); + movptr(val_addr, NULL_WORD); + NOT_LP64(movptr(val_addr1, NULL_WORD);) +} + + +void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { + if (JvmtiExport::can_force_early_return()) { + Label L; + Register tmp = LP64_ONLY(c_rarg0) NOT_LP64(java_thread); + Register rthread = LP64_ONLY(r15_thread) NOT_LP64(java_thread); + + movptr(tmp, Address(rthread, JavaThread::jvmti_thread_state_offset())); + testptr(tmp, tmp); + jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; + + // Initiate earlyret handling only if it is not already being processed. + // If the flag has the earlyret_processing bit set, it means that this code + // is called *during* earlyret handling - we don't want to reenter. + movl(tmp, Address(tmp, JvmtiThreadState::earlyret_state_offset())); + cmpl(tmp, JvmtiThreadState::earlyret_pending); + jcc(Assembler::notEqual, L); + + // Call Interpreter::remove_activation_early_entry() to get the address of the + // same-named entrypoint in the generated interpreter code. + NOT_LP64(get_thread(java_thread);) + movptr(tmp, Address(rthread, JavaThread::jvmti_thread_state_offset())); +#ifdef _LP64 + movl(tmp, Address(tmp, JvmtiThreadState::earlyret_tos_offset())); + call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), tmp); +#else + pushl(Address(tmp, JvmtiThreadState::earlyret_tos_offset())); + call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), 1); +#endif // _LP64 + jmp(rax); + bind(L); + NOT_LP64(get_thread(java_thread);) + } +} + +void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { + assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); + load_unsigned_short(reg, Address(_bcp_register, bcp_offset)); + bswapl(reg); + shrl(reg, 16); +} + +void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index, + int bcp_offset, + size_t index_size) { + assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + if (index_size == sizeof(u2)) { + load_unsigned_short(index, Address(_bcp_register, bcp_offset)); + } else if (index_size == sizeof(u4)) { + movl(index, Address(_bcp_register, bcp_offset)); + // Check if the secondary index definition is still ~x, otherwise + // we have to change the following assembler code to calculate the + // plain index. + assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); + notl(index); // convert to plain index + } else if (index_size == sizeof(u1)) { + load_unsigned_byte(index, Address(_bcp_register, bcp_offset)); + } else { + ShouldNotReachHere(); + } +} + +void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, + Register index, + int bcp_offset, + size_t index_size) { + assert_different_registers(cache, index); + get_cache_index_at_bcp(index, bcp_offset, index_size); + movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); + assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); + // convert from field index to ConstantPoolCacheEntry index + assert(exact_log2(in_words(ConstantPoolCacheEntry::size())) == 2, "else change next line"); + shll(index, 2); +} + +void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache, + Register index, + Register bytecode, + int byte_no, + int bcp_offset, + size_t index_size) { + get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size); + // We use a 32-bit load here since the layout of 64-bit words on + // little-endian machines allow us that. + movl(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset())); + const int shift_count = (1 + byte_no) * BitsPerByte; + assert((byte_no == TemplateTable::f1_byte && shift_count == ConstantPoolCacheEntry::bytecode_1_shift) || + (byte_no == TemplateTable::f2_byte && shift_count == ConstantPoolCacheEntry::bytecode_2_shift), + "correct shift count"); + shrl(bytecode, shift_count); + assert(ConstantPoolCacheEntry::bytecode_1_mask == ConstantPoolCacheEntry::bytecode_2_mask, "common mask"); + andl(bytecode, ConstantPoolCacheEntry::bytecode_1_mask); +} + +void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, + Register tmp, + int bcp_offset, + size_t index_size) { + assert(cache != tmp, "must use different register"); + get_cache_index_at_bcp(tmp, bcp_offset, index_size); + assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); + // convert from field index to ConstantPoolCacheEntry index + // and from word offset to byte offset + assert(exact_log2(in_bytes(ConstantPoolCacheEntry::size_in_bytes())) == 2 + LogBytesPerWord, "else change next line"); + shll(tmp, 2 + LogBytesPerWord); + movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); + // skip past the header + addptr(cache, in_bytes(ConstantPoolCache::base_offset())); + addptr(cache, tmp); // construct pointer to cache entry +} + +// Load object from cpool->resolved_references(index) +void InterpreterMacroAssembler::load_resolved_reference_at_index( + Register result, Register index) { + assert_different_registers(result, index); + // convert from field index to resolved_references() index and from + // word index to byte offset. Since this is a java object, it can be compressed + Register tmp = index; // reuse + shll(tmp, LogBytesPerHeapOop); + + get_constant_pool(result); + // load pointer for resolved_references[] objArray + movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + // JNIHandles::resolve(obj); + movptr(result, Address(result, 0)); + // Add in the index + addptr(result, tmp); + load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); +} + + +// Generate a subtype check: branch to ok_is_subtype if sub_klass is a +// subtype of super_klass. +// +// Args: +// rax: superklass +// Rsub_klass: subklass +// +// Kills: +// rcx, rdi +void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, + Label& ok_is_subtype) { + assert(Rsub_klass != rax, "rax holds superklass"); + LP64_ONLY(assert(Rsub_klass != r14, "r14 holds locals");) + LP64_ONLY(assert(Rsub_klass != r13, "r13 holds bcp");) + assert(Rsub_klass != rcx, "rcx holds 2ndary super array length"); + assert(Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr"); + + // Profile the not-null value's klass. + profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, reloads rdi + + // Do the check. + check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx + + // Profile the failure of the check. + profile_typecheck_failed(rcx); // blows rcx +} + + +#ifndef _LP64 +void InterpreterMacroAssembler::f2ieee() { + if (IEEEPrecision) { + fstp_s(Address(rsp, 0)); + fld_s(Address(rsp, 0)); + } +} + + +void InterpreterMacroAssembler::d2ieee() { + if (IEEEPrecision) { + fstp_d(Address(rsp, 0)); + fld_d(Address(rsp, 0)); + } +} +#endif // _LP64 + +// Java Expression Stack + +void InterpreterMacroAssembler::pop_ptr(Register r) { + pop(r); +} + +void InterpreterMacroAssembler::push_ptr(Register r) { + push(r); +} + +void InterpreterMacroAssembler::push_i(Register r) { + push(r); +} + +#ifdef _LP64 +void InterpreterMacroAssembler::pop_i(Register r) { + // XXX can't use pop currently, upper half non clean + movl(r, Address(rsp, 0)); + addptr(rsp, wordSize); +} + +void InterpreterMacroAssembler::pop_l(Register r) { + movq(r, Address(rsp, 0)); + addptr(rsp, 2 * Interpreter::stackElementSize); +} + +void InterpreterMacroAssembler::pop_f(XMMRegister r) { + movflt(r, Address(rsp, 0)); + addptr(rsp, wordSize); +} + +void InterpreterMacroAssembler::pop_d(XMMRegister r) { + movdbl(r, Address(rsp, 0)); + addptr(rsp, 2 * Interpreter::stackElementSize); +} + +void InterpreterMacroAssembler::push_l(Register r) { + subptr(rsp, 2 * wordSize); + movq(Address(rsp, 0), r); +} + +void InterpreterMacroAssembler::push_f(XMMRegister r) { + subptr(rsp, wordSize); + movflt(Address(rsp, 0), r); +} + +void InterpreterMacroAssembler::push_d(XMMRegister r) { + subptr(rsp, 2 * wordSize); + movdbl(Address(rsp, 0), r); +} + +void InterpreterMacroAssembler::pop(TosState state) { + switch (state) { + case atos: pop_ptr(); break; + case btos: + case ctos: + case stos: + case itos: pop_i(); break; + case ltos: pop_l(); break; + case ftos: pop_f(); break; + case dtos: pop_d(); break; + case vtos: /* nothing to do */ break; + default: ShouldNotReachHere(); + } + verify_oop(rax, state); +} + +void InterpreterMacroAssembler::push(TosState state) { + verify_oop(rax, state); + switch (state) { + case atos: push_ptr(); break; + case btos: + case ctos: + case stos: + case itos: push_i(); break; + case ltos: push_l(); break; + case ftos: push_f(); break; + case dtos: push_d(); break; + case vtos: /* nothing to do */ break; + default : ShouldNotReachHere(); + } +} +#else +void InterpreterMacroAssembler::pop_i(Register r) { + pop(r); +} + +void InterpreterMacroAssembler::pop_l(Register lo, Register hi) { + pop(lo); + pop(hi); +} + +void InterpreterMacroAssembler::pop_f() { + fld_s(Address(rsp, 0)); + addptr(rsp, 1 * wordSize); +} + +void InterpreterMacroAssembler::pop_d() { + fld_d(Address(rsp, 0)); + addptr(rsp, 2 * wordSize); +} + + +void InterpreterMacroAssembler::pop(TosState state) { + switch (state) { + case atos: pop_ptr(rax); break; + case btos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: pop_i(rax); break; + case ltos: pop_l(rax, rdx); break; + case ftos: pop_f(); break; + case dtos: pop_d(); break; + case vtos: /* nothing to do */ break; + default : ShouldNotReachHere(); + } + verify_oop(rax, state); +} + + +void InterpreterMacroAssembler::push_l(Register lo, Register hi) { + push(hi); + push(lo); +} + +void InterpreterMacroAssembler::push_f() { + // Do not schedule for no AGI! Never write beyond rsp! + subptr(rsp, 1 * wordSize); + fstp_s(Address(rsp, 0)); +} + +void InterpreterMacroAssembler::push_d(Register r) { + // Do not schedule for no AGI! Never write beyond rsp! + subptr(rsp, 2 * wordSize); + fstp_d(Address(rsp, 0)); +} + + +void InterpreterMacroAssembler::push(TosState state) { + verify_oop(rax, state); + switch (state) { + case atos: push_ptr(rax); break; + case btos: // fall through + case ctos: // fall through + case stos: // fall through + case itos: push_i(rax); break; + case ltos: push_l(rax, rdx); break; + case ftos: push_f(); break; + case dtos: push_d(rax); break; + case vtos: /* nothing to do */ break; + default : ShouldNotReachHere(); + } +} +#endif // _LP64 + + +// Helpers for swap and dup +void InterpreterMacroAssembler::load_ptr(int n, Register val) { + movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); +} + +void InterpreterMacroAssembler::store_ptr(int n, Register val) { + movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); +} + + +void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { + // set sender sp + lea(_bcp_register, Address(rsp, wordSize)); + // record last_sp + movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), _bcp_register); +} + + +// Jump to from_interpreted entry of a call unless single stepping is possible +// in this thread in which case we must call the i2i entry +void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { + prepare_to_jump_from_interpreted(); + + if (JvmtiExport::can_post_interpreter_events()) { + Label run_compiled_code; + // JVMTI events, such as single-stepping, are implemented partly by avoiding running + // compiled code in threads for which the event is enabled. Check here for + // interp_only_mode if these events CAN be enabled. + // interp_only is an int, on little endian it is sufficient to test the byte only + // Is a cmpl faster? + LP64_ONLY(temp = r15_thread;) + NOT_LP64(get_thread(temp);) + cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0); + jccb(Assembler::zero, run_compiled_code); + jmp(Address(method, Method::interpreter_entry_offset())); + bind(run_compiled_code); + } + + jmp(Address(method, Method::from_interpreted_offset())); +} + +// The following two routines provide a hook so that an implementation +// can schedule the dispatch in two parts. x86 does not do this. +void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { + // Nothing x86 specific to be done here +} + +void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { + dispatch_next(state, step); +} + +void InterpreterMacroAssembler::dispatch_base(TosState state, + address* table, + bool verifyoop) { + verify_FPU(1, state); + if (VerifyActivationFrameSize) { + Label L; + mov(rcx, rbp); + subptr(rcx, rsp); + int32_t min_frame_size = + (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * + wordSize; + cmpptr(rcx, (int32_t)min_frame_size); + jcc(Assembler::greaterEqual, L); + stop("broken stack frame"); + bind(L); + } + if (verifyoop) { + verify_oop(rax, state); + } +#ifdef _LP64 + lea(rscratch1, ExternalAddress((address)table)); + jmp(Address(rscratch1, rbx, Address::times_8)); +#else + Address index(noreg, rbx, Address::times_ptr); + ExternalAddress tbl((address)table); + ArrayAddress dispatch(tbl, index); + jump(dispatch); +#endif // _LP64 +} + +void InterpreterMacroAssembler::dispatch_only(TosState state) { + dispatch_base(state, Interpreter::dispatch_table(state)); +} + +void InterpreterMacroAssembler::dispatch_only_normal(TosState state) { + dispatch_base(state, Interpreter::normal_table(state)); +} + +void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) { + dispatch_base(state, Interpreter::normal_table(state), false); +} + + +void InterpreterMacroAssembler::dispatch_next(TosState state, int step) { + // load next bytecode (load before advancing _bcp_register to prevent AGI) + load_unsigned_byte(rbx, Address(_bcp_register, step)); + // advance _bcp_register + increment(_bcp_register, step); + dispatch_base(state, Interpreter::dispatch_table(state)); +} + +void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { + // load current bytecode + load_unsigned_byte(rbx, Address(_bcp_register, 0)); + dispatch_base(state, table); +} + +// remove activation +// +// Unlock the receiver if this is a synchronized method. +// Unlock any Java monitors from syncronized blocks. +// Remove the activation from the stack. +// +// If there are locked Java monitors +// If throw_monitor_exception +// throws IllegalMonitorStateException +// Else if install_monitor_exception +// installs IllegalMonitorStateException +// Else +// no error processing +void InterpreterMacroAssembler::remove_activation( + TosState state, + Register ret_addr, + bool throw_monitor_exception, + bool install_monitor_exception, + bool notify_jvmdi) { + // Note: Registers rdx xmm0 may be in use for the + // result check if synchronized method + Label unlocked, unlock, no_unlock; + + const Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + const Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rdx); + const Register rmon = LP64_ONLY(c_rarg1) NOT_LP64(rcx); + // monitor pointers need different register + // because rdx may have the result in it + NOT_LP64(get_thread(rcx);) + + // get the value of _do_not_unlock_if_synchronized into rdx + const Address do_not_unlock_if_synchronized(rthread, + in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); + movbool(rbx, do_not_unlock_if_synchronized); + movbool(do_not_unlock_if_synchronized, false); // reset the flag + + // get method access flags + movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); + movl(rcx, Address(rcx, Method::access_flags_offset())); + testl(rcx, JVM_ACC_SYNCHRONIZED); + jcc(Assembler::zero, unlocked); + + // Don't unlock anything if the _do_not_unlock_if_synchronized flag + // is set. + testbool(rbx); + jcc(Assembler::notZero, no_unlock); + + // unlock monitor + push(state); // save result + + // BasicObjectLock will be first in list, since this is a + // synchronized method. However, need to check that the object has + // not been unlocked by an explicit monitorexit bytecode. + const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * + wordSize - (int) sizeof(BasicObjectLock)); + // We use c_rarg1/rdx so that if we go slow path it will be the correct + // register for unlock_object to pass to VM directly + lea(robj, monitor); // address of first monitor + + movptr(rax, Address(robj, BasicObjectLock::obj_offset_in_bytes())); + testptr(rax, rax); + jcc(Assembler::notZero, unlock); + + pop(state); + if (throw_monitor_exception) { + // Entry already unlocked, need to throw exception + NOT_LP64(empty_FPU_stack();) // remove possible return value from FPU-stack, otherwise stack could overflow + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_illegal_monitor_state_exception)); + should_not_reach_here(); + } else { + // Monitor already unlocked during a stack unroll. If requested, + // install an illegal_monitor_state_exception. Continue with + // stack unrolling. + if (install_monitor_exception) { + NOT_LP64(empty_FPU_stack();) + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::new_illegal_monitor_state_exception)); + } + jmp(unlocked); + } + + bind(unlock); + unlock_object(robj); + pop(state); + + // Check that for block-structured locking (i.e., that all locked + // objects has been unlocked) + bind(unlocked); + + // rax, rdx: Might contain return value + + // Check that all monitors are unlocked + { + Label loop, exception, entry, restart; + const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; + 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); + + bind(restart); + // We use c_rarg1 so that if we go slow path it will be the correct + // register for unlock_object to pass to VM directly + movptr(rmon, 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 + jmp(entry); + + // Entry already locked, need to throw exception + bind(exception); + + if (throw_monitor_exception) { + // Throw exception + NOT_LP64(empty_FPU_stack();) + MacroAssembler::call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime:: + throw_illegal_monitor_state_exception)); + should_not_reach_here(); + } else { + // Stack unrolling. Unlock object and install illegal_monitor_exception. + // Unlock does not block, so don't have to worry about the frame. + // We don't have to preserve c_rarg1 since we are going to throw an exception. + + push(state); + mov(robj, rmon); // nop if robj and rmon are the same + unlock_object(robj); + pop(state); + + if (install_monitor_exception) { + NOT_LP64(empty_FPU_stack();) + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime:: + new_illegal_monitor_state_exception)); + } + + jmp(restart); + } + + bind(loop); + // check if current entry is used + cmpptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL); + jcc(Assembler::notEqual, exception); + + addptr(rmon, entry_size); // otherwise advance to next entry + bind(entry); + cmpptr(rmon, rbx); // check if bottom reached + jcc(Assembler::notEqual, loop); // if not at bottom then check this entry + } + + bind(no_unlock); + + // jvmti support + if (notify_jvmdi) { + notify_method_exit(state, NotifyJVMTI); // preserve TOSCA + } else { + notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA + } + + // remove activation + // get sender sp + movptr(rbx, + Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); + leave(); // remove frame anchor + pop(ret_addr); // get return address + mov(rsp, rbx); // set sp to sender sp +#ifndef _LP64 + if (UseSSE) { + // float and double are returned in xmm register in SSE-mode + if (state == ftos && UseSSE >= 1) { + subptr(rsp, wordSize); + fstp_s(Address(rsp, 0)); + movflt(xmm0, Address(rsp, 0)); + addptr(rsp, wordSize); + } else if (state == dtos && UseSSE >= 2) { + subptr(rsp, 2*wordSize); + fstp_d(Address(rsp, 0)); + movdbl(xmm0, Address(rsp, 0)); + addptr(rsp, 2*wordSize); + } + } +#endif // _LP64 +} +#endif // !CC_INTERP + +void InterpreterMacroAssembler::get_method_counters(Register method, + Register mcs, Label& skip) { + Label has_counters; + movptr(mcs, Address(method, Method::method_counters_offset())); + testptr(mcs, mcs); + jcc(Assembler::notZero, has_counters); + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::build_method_counters), method); + movptr(mcs, Address(method,Method::method_counters_offset())); + testptr(mcs, mcs); + jcc(Assembler::zero, skip); // No MethodCounters allocated, OutOfMemory + bind(has_counters); +} + + +// Lock object +// +// Args: +// rdx, c_rarg1: BasicObjectLock to be used for locking +// +// Kills: +// rax +// rscratch1 (scratch regs) +void InterpreterMacroAssembler::lock_object(Register lock_reg) { + assert(lock_reg == LP64_ONLY(c_rarg1) NOT_LP64(rdx), + "The argument is only for looks. It must be c_rarg1"); + + if (UseHeavyMonitors) { + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), + lock_reg); + } else { + Label done; + + const Register swap_reg = rax; // Must use rax for cmpxchg instruction + const Register obj_reg = LP64_ONLY(c_rarg3) NOT_LP64(rcx); // Will contain the oop + + const int obj_offset = BasicObjectLock::obj_offset_in_bytes(); + const int lock_offset = BasicObjectLock::lock_offset_in_bytes (); + const int mark_offset = lock_offset + + BasicLock::displaced_header_offset_in_bytes(); + + Label slow_case; + + // Load object pointer into obj_reg + movptr(obj_reg, Address(lock_reg, obj_offset)); + + if (UseBiasedLocking) { + biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, done, &slow_case); + } + + // Load immediate 1 into swap_reg %rax + movl(swap_reg, (int32_t)1); + + // Load (object->mark() | 1) into swap_reg %rax + orptr(swap_reg, Address(obj_reg, 0)); + + // Save (object->mark() | 1) into BasicLock's displaced header + movptr(Address(lock_reg, mark_offset), swap_reg); + + assert(lock_offset == 0, + "displached header must be first word in BasicObjectLock"); + + if (os::is_MP()) lock(); + cmpxchgptr(lock_reg, Address(obj_reg, 0)); + if (PrintBiasedLockingStatistics) { + cond_inc32(Assembler::zero, + ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); + } + jcc(Assembler::zero, done); + + const int zero_bits = LP64_ONLY(7) NOT_LP64(3); + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & zero_bits) == 0, and + // 2) rsp <= mark < mark + os::pagesize() + // + // These 3 tests can be done by evaluating the following + // expression: ((mark - rsp) & (zero_bits - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant bits clear. + // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg + subptr(swap_reg, rsp); + andptr(swap_reg, zero_bits - os::vm_page_size()); + + // Save the test result, for recursive case, the result is zero + movptr(Address(lock_reg, mark_offset), swap_reg); + + if (PrintBiasedLockingStatistics) { + cond_inc32(Assembler::zero, + ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); + } + jcc(Assembler::zero, done); + + bind(slow_case); + + // Call the runtime routine for slow case + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), + lock_reg); + + bind(done); + } +} + + +// Unlocks an object. Used in monitorexit bytecode and +// remove_activation. Throws an IllegalMonitorException if object is +// not locked by current thread. +// +// Args: +// rdx, c_rarg1: BasicObjectLock for lock +// +// Kills: +// rax +// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ... (param regs) +// rscratch1, rscratch2 (scratch regs) +// rax, rbx, rcx, rdx +void InterpreterMacroAssembler::unlock_object(Register lock_reg) { + assert(lock_reg == LP64_ONLY(c_rarg1) NOT_LP64(rdx), + "The argument is only for looks. It must be c_rarg1"); + + if (UseHeavyMonitors) { + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), + lock_reg); + } else { + Label done; + + const Register swap_reg = rax; // Must use rax for cmpxchg instruction + const Register header_reg = LP64_ONLY(c_rarg2) NOT_LP64(rbx); // Will contain the old oopMark + const Register obj_reg = LP64_ONLY(c_rarg3) NOT_LP64(rcx); // Will contain the oop + + save_bcp(); // Save in case of exception + + // Convert from BasicObjectLock structure to object and BasicLock + // structure Store the BasicLock address into %rax + lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); + + // Load oop into obj_reg(%c_rarg3) + movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); + + // Free entry + movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); + + if (UseBiasedLocking) { + biased_locking_exit(obj_reg, header_reg, done); + } + + // Load the old header from BasicLock structure + movptr(header_reg, Address(swap_reg, + BasicLock::displaced_header_offset_in_bytes())); + + // Test for recursion + testptr(header_reg, header_reg); + + // zero for recursive case + jcc(Assembler::zero, done); + + // Atomic swap back the old header + if (os::is_MP()) lock(); + cmpxchgptr(header_reg, Address(obj_reg, 0)); + + // zero for recursive case + jcc(Assembler::zero, done); + + // Call the runtime routine for slow case. + movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), + obj_reg); // restore obj + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), + lock_reg); + + bind(done); + + restore_bcp(); + } +} +#ifndef CC_INTERP +void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, + Label& zero_continue) { + assert(ProfileInterpreter, "must be profiling interpreter"); + movptr(mdp, Address(rbp, frame::interpreter_frame_mdp_offset * wordSize)); + testptr(mdp, mdp); + jcc(Assembler::zero, zero_continue); +} + + +// Set the method data pointer for the current bcp. +void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { + assert(ProfileInterpreter, "must be profiling interpreter"); + Label set_mdp; + push(rax); + push(rbx); + + get_method(rbx); + // Test MDO to avoid the call if it is NULL. + movptr(rax, Address(rbx, in_bytes(Method::method_data_offset()))); + testptr(rax, rax); + jcc(Assembler::zero, set_mdp); + // rbx: method + // _bcp_register: bcp + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, _bcp_register); + // rax: mdi + // mdo is guaranteed to be non-zero here, we checked for it before the call. + movptr(rbx, Address(rbx, in_bytes(Method::method_data_offset()))); + addptr(rbx, in_bytes(MethodData::data_offset())); + addptr(rax, rbx); + bind(set_mdp); + movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), rax); + pop(rbx); + pop(rax); +} + +void InterpreterMacroAssembler::verify_method_data_pointer() { + assert(ProfileInterpreter, "must be profiling interpreter"); +#ifdef ASSERT + Label verify_continue; + push(rax); + push(rbx); + Register arg3_reg = LP64_ONLY(c_rarg3) NOT_LP64(rcx); + Register arg2_reg = LP64_ONLY(c_rarg2) NOT_LP64(rdx); + push(arg3_reg); + push(arg2_reg); + test_method_data_pointer(arg3_reg, verify_continue); // If mdp is zero, continue + get_method(rbx); + + // If the mdp is valid, it will point to a DataLayout header which is + // consistent with the bcp. The converse is highly probable also. + load_unsigned_short(arg2_reg, + Address(arg3_reg, in_bytes(DataLayout::bci_offset()))); + addptr(arg2_reg, Address(rbx, Method::const_offset())); + lea(arg2_reg, Address(arg2_reg, ConstMethod::codes_offset())); + cmpptr(arg2_reg, _bcp_register); + jcc(Assembler::equal, verify_continue); + // rbx: method + // _bcp_register: bcp + // c_rarg3: mdp + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), + rbx, _bcp_register, arg3_reg); + bind(verify_continue); + pop(arg2_reg); + pop(arg3_reg); + pop(rbx); + pop(rax); +#endif // ASSERT +} + + +void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, + int constant, + Register value) { + assert(ProfileInterpreter, "must be profiling interpreter"); + Address data(mdp_in, constant); + movptr(data, value); +} + + +void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, + int constant, + bool decrement) { + // Counter address + Address data(mdp_in, constant); + + increment_mdp_data_at(data, decrement); +} + +void InterpreterMacroAssembler::increment_mdp_data_at(Address data, + bool decrement) { + assert(ProfileInterpreter, "must be profiling interpreter"); + // %%% this does 64bit counters at best it is wasting space + // at worst it is a rare bug when counters overflow + + if (decrement) { + // Decrement the register. Set condition codes. + addptr(data, (int32_t) -DataLayout::counter_increment); + // If the decrement causes the counter to overflow, stay negative + Label L; + jcc(Assembler::negative, L); + addptr(data, (int32_t) DataLayout::counter_increment); + bind(L); + } else { + assert(DataLayout::counter_increment == 1, + "flow-free idiom only works with 1"); + // Increment the register. Set carry flag. + addptr(data, DataLayout::counter_increment); + // If the increment causes the counter to overflow, pull back by 1. + sbbptr(data, (int32_t)0); + } +} + + +void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, + Register reg, + int constant, + bool decrement) { + Address data(mdp_in, reg, Address::times_1, constant); + + increment_mdp_data_at(data, decrement); +} + +void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, + int flag_byte_constant) { + assert(ProfileInterpreter, "must be profiling interpreter"); + int header_offset = in_bytes(DataLayout::header_offset()); + int header_bits = DataLayout::flag_mask_to_header_mask(flag_byte_constant); + // Set the flag + orl(Address(mdp_in, header_offset), header_bits); +} + + + +void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, + int offset, + Register value, + Register test_value_out, + Label& not_equal_continue) { + assert(ProfileInterpreter, "must be profiling interpreter"); + if (test_value_out == noreg) { + cmpptr(value, Address(mdp_in, offset)); + } else { + // Put the test value into a register, so caller can use it: + movptr(test_value_out, Address(mdp_in, offset)); + cmpptr(test_value_out, value); + } + jcc(Assembler::notEqual, not_equal_continue); +} + + +void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, + int offset_of_disp) { + assert(ProfileInterpreter, "must be profiling interpreter"); + Address disp_address(mdp_in, offset_of_disp); + addptr(mdp_in, disp_address); + movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); +} + + +void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, + Register reg, + int offset_of_disp) { + assert(ProfileInterpreter, "must be profiling interpreter"); + Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); + addptr(mdp_in, disp_address); + movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); +} + + +void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, + int constant) { + assert(ProfileInterpreter, "must be profiling interpreter"); + addptr(mdp_in, constant); + movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); +} + + +void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { + assert(ProfileInterpreter, "must be profiling interpreter"); + push(return_bci); // save/restore across call_VM + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), + return_bci); + pop(return_bci); +} + + +void InterpreterMacroAssembler::profile_taken_branch(Register mdp, + Register bumped_count) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + // Otherwise, assign to mdp + test_method_data_pointer(mdp, profile_continue); + + // We are taking a branch. Increment the taken count. + // We inline increment_mdp_data_at to return bumped_count in a register + //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); + Address data(mdp, in_bytes(JumpData::taken_offset())); + movptr(bumped_count, data); + assert(DataLayout::counter_increment == 1, + "flow-free idiom only works with 1"); + addptr(bumped_count, DataLayout::counter_increment); + sbbptr(bumped_count, 0); + movptr(data, bumped_count); // Store back out + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // We are taking a branch. Increment the not taken count. + increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); + + // The method data pointer needs to be updated to correspond to + // the next bytecode + update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_call(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // We are making a call. Increment the count. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_final_call(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // We are making a call. Increment the count. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_constant(mdp, + in_bytes(VirtualCallData:: + virtual_call_data_size())); + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_virtual_call(Register receiver, + Register mdp, + Register reg2, + bool receiver_can_be_null) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + Label skip_receiver_profile; + if (receiver_can_be_null) { + Label not_null; + testptr(receiver, receiver); + jccb(Assembler::notZero, not_null); + // We are making a call. Increment the count for null receiver. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + jmp(skip_receiver_profile); + bind(not_null); + } + + // Record the receiver type. + record_klass_in_profile(receiver, mdp, reg2, true); + bind(skip_receiver_profile); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_constant(mdp, + in_bytes(VirtualCallData:: + virtual_call_data_size())); + bind(profile_continue); + } +} + +// This routine creates a state machine for updating the multi-row +// type profile at a virtual call site (or other type-sensitive bytecode). +// The machine visits each row (of receiver/count) until the receiver type +// is found, or until it runs out of rows. At the same time, it remembers +// the location of the first empty row. (An empty row records null for its +// receiver, and can be allocated for a newly-observed receiver type.) +// Because there are two degrees of freedom in the state, a simple linear +// search will not work; it must be a decision tree. Hence this helper +// function is recursive, to generate the required tree structured code. +// It's the interpreter, so we are trading off code space for speed. +// See below for example code. +void InterpreterMacroAssembler::record_klass_in_profile_helper( + Register receiver, Register mdp, + Register reg2, int start_row, + Label& done, bool is_virtual_call) { + if (TypeProfileWidth == 0) { + if (is_virtual_call) { + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + } + return; + } + + int last_row = VirtualCallData::row_limit() - 1; + assert(start_row <= last_row, "must be work left to do"); + // Test this row for both the receiver and for null. + // Take any of three different outcomes: + // 1. found receiver => increment count and goto done + // 2. found null => keep looking for case 1, maybe allocate this cell + // 3. found something else => keep looking for cases 1 and 2 + // Case 3 is handled by a recursive call. + for (int row = start_row; row <= last_row; row++) { + Label next_test; + bool test_for_null_also = (row == start_row); + + // See if the receiver is receiver[n]. + int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); + test_mdp_data_at(mdp, recvr_offset, receiver, + (test_for_null_also ? reg2 : noreg), + next_test); + // (Reg2 now contains the receiver from the CallData.) + + // The receiver is receiver[n]. Increment count[n]. + int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); + increment_mdp_data_at(mdp, count_offset); + jmp(done); + bind(next_test); + + if (test_for_null_also) { + Label found_null; + // Failed the equality check on receiver[n]... Test for null. + testptr(reg2, reg2); + if (start_row == last_row) { + // The only thing left to do is handle the null case. + if (is_virtual_call) { + jccb(Assembler::zero, found_null); + // Receiver did not match any saved receiver and there is no empty row for it. + // Increment total counter to indicate polymorphic case. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + jmp(done); + bind(found_null); + } else { + jcc(Assembler::notZero, done); + } + break; + } + // Since null is rare, make it be the branch-taken case. + jcc(Assembler::zero, found_null); + + // Put all the "Case 3" tests here. + record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); + + // Found a null. Keep searching for a matching receiver, + // but remember that this is an empty (unused) slot. + bind(found_null); + } + } + + // In the fall-through case, we found no matching receiver, but we + // observed the receiver[start_row] is NULL. + + // Fill in the receiver field and increment the count. + int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); + set_mdp_data_at(mdp, recvr_offset, receiver); + int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); + movl(reg2, DataLayout::counter_increment); + set_mdp_data_at(mdp, count_offset, reg2); + if (start_row > 0) { + jmp(done); + } +} + +// Example state machine code for three profile rows: +// // main copy of decision tree, rooted at row[1] +// if (row[0].rec == rec) { row[0].incr(); goto done; } +// if (row[0].rec != NULL) { +// // inner copy of decision tree, rooted at row[1] +// if (row[1].rec == rec) { row[1].incr(); goto done; } +// if (row[1].rec != NULL) { +// // degenerate decision tree, rooted at row[2] +// if (row[2].rec == rec) { row[2].incr(); goto done; } +// if (row[2].rec != NULL) { count.incr(); goto done; } // overflow +// row[2].init(rec); goto done; +// } else { +// // remember row[1] is empty +// if (row[2].rec == rec) { row[2].incr(); goto done; } +// row[1].init(rec); goto done; +// } +// } else { +// // remember row[0] is empty +// if (row[1].rec == rec) { row[1].incr(); goto done; } +// if (row[2].rec == rec) { row[2].incr(); goto done; } +// row[0].init(rec); goto done; +// } +// done: + +void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, + Register mdp, Register reg2, + bool is_virtual_call) { + assert(ProfileInterpreter, "must be profiling"); + Label done; + + record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); + + bind (done); +} + +void InterpreterMacroAssembler::profile_ret(Register return_bci, + Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + uint row; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // Update the total ret count. + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + + for (row = 0; row < RetData::row_limit(); row++) { + Label next_test; + + // See if return_bci is equal to bci[n]: + test_mdp_data_at(mdp, + in_bytes(RetData::bci_offset(row)), + return_bci, noreg, + next_test); + + // return_bci is equal to bci[n]. Increment the count. + increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); + + // The method data pointer needs to be updated to reflect the new target. + update_mdp_by_offset(mdp, + in_bytes(RetData::bci_displacement_offset(row))); + jmp(profile_continue); + bind(next_test); + } + + update_mdp_for_ret(return_bci); + + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_null_seen(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); + + // The method data pointer needs to be updated. + int mdp_delta = in_bytes(BitData::bit_data_size()); + if (TypeProfileCasts) { + mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + } + update_mdp_by_constant(mdp, mdp_delta); + + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { + if (ProfileInterpreter && TypeProfileCasts) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + int count_offset = in_bytes(CounterData::count_offset()); + // Back up the address, since we have already bumped the mdp. + count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); + + // *Decrement* the counter. We expect to see zero or small negatives. + increment_mdp_data_at(mdp, count_offset, true); + + bind (profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // The method data pointer needs to be updated. + int mdp_delta = in_bytes(BitData::bit_data_size()); + if (TypeProfileCasts) { + mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + + // Record the object type. + record_klass_in_profile(klass, mdp, reg2, false); + NOT_LP64(assert(reg2 == rdi, "we know how to fix this blown reg");) + NOT_LP64(restore_locals();) // Restore EDI + } + update_mdp_by_constant(mdp, mdp_delta); + + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_switch_default(Register mdp) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // Update the default case count + increment_mdp_data_at(mdp, + in_bytes(MultiBranchData::default_count_offset())); + + // The method data pointer needs to be updated. + update_mdp_by_offset(mdp, + in_bytes(MultiBranchData:: + default_displacement_offset())); + + bind(profile_continue); + } +} + + +void InterpreterMacroAssembler::profile_switch_case(Register index, + Register mdp, + Register reg2) { + if (ProfileInterpreter) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + // Build the base (index * per_case_size_in_bytes()) + + // case_array_offset_in_bytes() + movl(reg2, in_bytes(MultiBranchData::per_case_size())); + imulptr(index, reg2); // XXX l ? + addptr(index, in_bytes(MultiBranchData::case_array_offset())); // XXX l ? + + // Update the case count + increment_mdp_data_at(mdp, + index, + in_bytes(MultiBranchData::relative_count_offset())); + + // The method data pointer needs to be updated. + update_mdp_by_offset(mdp, + index, + in_bytes(MultiBranchData:: + relative_displacement_offset())); + + bind(profile_continue); + } +} + + + +void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { + if (state == atos) { + MacroAssembler::verify_oop(reg); + } +} + +void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { +#ifndef _LP64 + if (state == ftos || state == dtos) MacroAssembler::verify_FPU(stack_depth); +#endif +} + +// Jump if ((*counter_addr += increment) & mask) satisfies the condition. +void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, + int increment, Address mask, + Register scratch, bool preloaded, + Condition cond, Label* where) { + if (!preloaded) { + movl(scratch, counter_addr); + } + incrementl(scratch, increment); + movl(counter_addr, scratch); + andl(scratch, mask); + jcc(cond, *where); +} +#endif // CC_INTERP + +void InterpreterMacroAssembler::notify_method_entry() { + // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to + // track stack depth. If it is possible to enter interp_only_mode we add + // the code to check if the event should be sent. + Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + Register rarg = LP64_ONLY(c_rarg1) NOT_LP64(rbx); + if (JvmtiExport::can_post_interpreter_events()) { + Label L; + NOT_LP64(get_thread(rthread);) + movl(rdx, Address(rthread, JavaThread::interp_only_mode_offset())); + testl(rdx, rdx); + jcc(Assembler::zero, L); + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_method_entry)); + bind(L); + } + + { + SkipIfEqual skip(this, &DTraceMethodProbes, false); + NOT_LP64(get_thread(rthread);) + get_method(rarg); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), + rthread, rarg); + } + + // RedefineClasses() tracing support for obsolete method entry + if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { + NOT_LP64(get_thread(rthread);) + get_method(rarg); + call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), + rthread, rarg); + } +} + + +void InterpreterMacroAssembler::notify_method_exit( + TosState state, NotifyMethodExitMode mode) { + // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to + // track stack depth. If it is possible to enter interp_only_mode we add + // the code to check if the event should be sent. + Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + Register rarg = LP64_ONLY(c_rarg1) NOT_LP64(rbx); + if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { + Label L; + // Note: frame::interpreter_frame_result has a dependency on how the + // method result is saved across the call to post_method_exit. If this + // is changed then the interpreter_frame_result implementation will + // need to be updated too. + + // For c++ interpreter the result is always stored at a known location in the frame + // template interpreter will leave it on the top of the stack. + NOT_CC_INTERP(push(state);) + NOT_LP64(get_thread(rthread);) + movl(rdx, Address(rthread, JavaThread::interp_only_mode_offset())); + testl(rdx, rdx); + jcc(Assembler::zero, L); + call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); + bind(L); + NOT_CC_INTERP(pop(state)); + } + + { + SkipIfEqual skip(this, &DTraceMethodProbes, false); + NOT_CC_INTERP(push(state)); + NOT_LP64(get_thread(rthread);) + get_method(rarg); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), + rthread, rarg); + NOT_CC_INTERP(pop(state)); + } +} diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/interp_masm_x86.hpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 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 @@ -35,12 +35,254 @@ class InterpreterMacroAssembler: public MacroAssembler { -#ifdef TARGET_ARCH_MODEL_x86_32 -# include "interp_masm_x86_32.hpp" -#endif -#ifdef TARGET_ARCH_MODEL_x86_64 -# include "interp_masm_x86_64.hpp" -#endif +#ifndef CC_INTERP + protected: + // Interpreter specific version of call_VM_base + virtual void call_VM_leaf_base(address entry_point, + int number_of_arguments); + + virtual void call_VM_base(Register oop_result, + Register java_thread, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions); + + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + + // base routine for all dispatches + void dispatch_base(TosState state, address* table, bool verifyoop = true); +#endif // CC_INTERP + + public: + InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), + _locals_register(LP64_ONLY(r14) NOT_LP64(rdi)), + _bcp_register(LP64_ONLY(r13) NOT_LP64(rsi)) {} + + void load_earlyret_value(TosState state); + +#ifdef CC_INTERP + void save_bcp() { /* not needed in c++ interpreter and harmless */ } + void restore_bcp() { /* not needed in c++ interpreter and harmless */ } + + // Helpers for runtime call arguments/results + void get_method(Register reg); + +#else + + // Interpreter-specific registers + void save_bcp() { + movptr(Address(rbp, frame::interpreter_frame_bcp_offset * wordSize), _bcp_register); + } + + void restore_bcp() { + movptr(_bcp_register, Address(rbp, frame::interpreter_frame_bcp_offset * wordSize)); + } + + void restore_locals() { + movptr(_locals_register, Address(rbp, frame::interpreter_frame_locals_offset * wordSize)); + } + + // Helpers for runtime call arguments/results + void get_method(Register reg) { + movptr(reg, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); + } + + void get_const(Register reg) { + get_method(reg); + movptr(reg, Address(reg, Method::const_offset())); + } + + void get_constant_pool(Register reg) { + get_const(reg); + movptr(reg, Address(reg, ConstMethod::constants_offset())); + } + + void get_constant_pool_cache(Register reg) { + get_constant_pool(reg); + movptr(reg, Address(reg, ConstantPool::cache_offset_in_bytes())); + } + + void get_cpool_and_tags(Register cpool, Register tags) { + get_constant_pool(cpool); + movptr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes())); + } + + void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); + void get_cache_and_index_at_bcp(Register cache, + Register index, + int bcp_offset, + size_t index_size = sizeof(u2)); + void get_cache_and_index_and_bytecode_at_bcp(Register cache, + Register index, + Register bytecode, + int byte_no, + int bcp_offset, + size_t index_size = sizeof(u2)); + void get_cache_entry_pointer_at_bcp(Register cache, + Register tmp, + int bcp_offset, + size_t index_size = sizeof(u2)); + void get_cache_index_at_bcp(Register index, + int bcp_offset, + size_t index_size = sizeof(u2)); + + // load cpool->resolved_references(index); + void load_resolved_reference_at_index(Register result, Register index); + + NOT_LP64(void f2ieee();) // truncate ftos to 32bits + NOT_LP64(void d2ieee();) // truncate dtos to 64bits + + // Expression stack + void pop_ptr(Register r = rax); + void pop_i(Register r = rax); + void push_ptr(Register r = rax); + void push_i(Register r = rax); + +#ifdef _LP64 + void pop_l(Register r = rax); + void pop_f(XMMRegister r = xmm0); + void pop_d(XMMRegister r = xmm0); + void push_l(Register r = rax); + void push_f(XMMRegister r = xmm0); + void push_d(XMMRegister r = xmm0); +#else + void pop_l(Register lo = rax, Register hi = rdx); + void pop_f(); + void pop_d(); + + void push_l(Register lo = rax, Register hi = rdx); + void push_d(Register r = rax); + void push_f(); +#endif // _LP64 + + void pop(Register r) { ((MacroAssembler*)this)->pop(r); } + void push(Register r) { ((MacroAssembler*)this)->push(r); } + void push(int32_t imm ) { ((MacroAssembler*)this)->push(imm); } + + void pop(TosState state); // transition vtos -> state + void push(TosState state); // transition state -> vtos + + // These are dummies to prevent surprise implicit conversions to Register + void pop(void* v); // Add unimplemented ambiguous method + void push(void* v); // Add unimplemented ambiguous method + + void empty_expression_stack() { + movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); + // NULL last_sp until next java call + movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + } + + // Helpers for swap and dup + void load_ptr(int n, Register val); + void store_ptr(int n, Register val); + + // Generate a subtype check: branch to ok_is_subtype if sub_klass is + // a subtype of super_klass. + void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); + + // Dispatching + void dispatch_prolog(TosState state, int step = 0); + void dispatch_epilog(TosState state, int step = 0); + // dispatch via rbx (assume rbx is loaded already) + void dispatch_only(TosState state); + // dispatch normal table via rbx (assume rbx is loaded already) + void dispatch_only_normal(TosState state); + void dispatch_only_noverify(TosState state); + // load rbx from [_bcp_register + step] and dispatch via rbx + void dispatch_next(TosState state, int step = 0); + // load rbx from [_bcp_register] and dispatch via rbx and table + void dispatch_via (TosState state, address* table); + + // jump to an invoked target + void prepare_to_jump_from_interpreted(); + void jump_from_interpreted(Register method, Register temp); + + // Returning from interpreted functions + // + // Removes the current activation (incl. unlocking of monitors) + // and sets up the return address. This code is also used for + // exception unwindwing. In that case, we do not want to throw + // IllegalMonitorStateExceptions, since that might get us into an + // infinite rethrow exception loop. + // Additionally this code is used for popFrame and earlyReturn. + // In popFrame case we want to skip throwing an exception, + // installing an exception, and notifying jvmdi. + // In earlyReturn case we only want to skip throwing an exception + // and installing an exception. + void remove_activation(TosState state, Register ret_addr, + bool throw_monitor_exception = true, + bool install_monitor_exception = true, + bool notify_jvmdi = true); +#endif // CC_INTERP + void get_method_counters(Register method, Register mcs, Label& skip); + + // Object locking + void lock_object (Register lock_reg); + void unlock_object(Register lock_reg); + +#ifndef CC_INTERP + + // Interpreter profiling operations + void set_method_data_pointer_for_bcp(); + void test_method_data_pointer(Register mdp, Label& zero_continue); + void verify_method_data_pointer(); + + void set_mdp_data_at(Register mdp_in, int constant, Register value); + void increment_mdp_data_at(Address data, bool decrement = false); + void increment_mdp_data_at(Register mdp_in, int constant, + bool decrement = false); + void increment_mdp_data_at(Register mdp_in, Register reg, int constant, + bool decrement = false); + void increment_mask_and_jump(Address counter_addr, + int increment, Address mask, + Register scratch, bool preloaded, + Condition cond, Label* where); + void set_mdp_flag_at(Register mdp_in, int flag_constant); + void test_mdp_data_at(Register mdp_in, int offset, Register value, + Register test_value_out, + Label& not_equal_continue); + + void record_klass_in_profile(Register receiver, Register mdp, + Register reg2, bool is_virtual_call); + void record_klass_in_profile_helper(Register receiver, Register mdp, + Register reg2, int start_row, + Label& done, bool is_virtual_call); + + void update_mdp_by_offset(Register mdp_in, int offset_of_offset); + void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); + void update_mdp_by_constant(Register mdp_in, int constant); + void update_mdp_for_ret(Register return_bci); + + void profile_taken_branch(Register mdp, Register bumped_count); + void profile_not_taken_branch(Register mdp); + void profile_call(Register mdp); + void profile_final_call(Register mdp); + void profile_virtual_call(Register receiver, Register mdp, + Register scratch2, + bool receiver_can_be_null = false); + void profile_ret(Register return_bci, Register mdp); + void profile_null_seen(Register mdp); + void profile_typecheck(Register mdp, Register klass, Register scratch); + void profile_typecheck_failed(Register mdp); + void profile_switch_default(Register mdp); + void profile_switch_case(Register index_in_scratch, Register mdp, + Register scratch2); + + // Debugging + // only if +VerifyOops && state == atos + void verify_oop(Register reg, TosState state = atos); + // only if +VerifyFPU && (state == ftos || state == dtos) + void verify_FPU(int stack_depth, TosState state = ftos); + +#endif // !CC_INTERP + + typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; + + // support for jvmti/dtrace + void notify_method_entry(); + void notify_method_exit(TosState state, NotifyMethodExitMode mode); private: diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Tue Mar 31 16:22:59 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1444 +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 "interp_masm_x86.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" -#include "oops/arrayOop.hpp" -#include "oops/markOop.hpp" -#include "oops/methodData.hpp" -#include "oops/method.hpp" -#include "prims/jvmtiExport.hpp" -#include "prims/jvmtiRedefineClassesTrace.hpp" -#include "prims/jvmtiThreadState.hpp" -#include "runtime/basicLock.hpp" -#include "runtime/biasedLocking.hpp" -#include "runtime/sharedRuntime.hpp" -#include "runtime/thread.inline.hpp" - - -// Implementation of InterpreterMacroAssembler -#ifdef CC_INTERP -void InterpreterMacroAssembler::get_method(Register reg) { - movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); - movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); -} -#endif // CC_INTERP - - -#ifndef CC_INTERP -void InterpreterMacroAssembler::call_VM_leaf_base( - address entry_point, - int number_of_arguments -) { - // interpreter specific - // - // Note: No need to save/restore bcp & locals (rsi & rdi) pointer - // since these are callee saved registers and no blocking/ - // GC can happen in leaf calls. - // Further Note: DO NOT save/restore bcp/locals. If a caller has - // already saved them so that it can use rsi/rdi as temporaries - // then a save/restore here will DESTROY the copy the caller - // saved! There used to be a save_bcp() that only happened in - // the ASSERT path (no restore_bcp). Which caused bizarre failures - // when jvm built with ASSERTs. -#ifdef ASSERT - { Label L; - cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - jcc(Assembler::equal, L); - stop("InterpreterMacroAssembler::call_VM_leaf_base: last_sp != NULL"); - bind(L); - } -#endif - // super call - MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); - // interpreter specific - - // Used to ASSERT that rsi/rdi were equal to frame's bcp/locals - // but since they may not have been saved (and we don't want to - // save them here (see note above) the assert is invalid. -} - - -void InterpreterMacroAssembler::call_VM_base( - Register oop_result, - Register java_thread, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions -) { -#ifdef ASSERT - { Label L; - cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - jcc(Assembler::equal, L); - stop("InterpreterMacroAssembler::call_VM_base: last_sp != NULL"); - bind(L); - } -#endif /* ASSERT */ - // interpreter specific - // - // Note: Could avoid restoring locals ptr (callee saved) - however doesn't - // really make a difference for these runtime calls, since they are - // slow anyway. Btw., bcp must be saved/restored since it may change - // due to GC. - assert(java_thread == noreg , "not expecting a precomputed java thread"); - save_bcp(); - // super call - MacroAssembler::call_VM_base(oop_result, java_thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); - // interpreter specific - restore_bcp(); - restore_locals(); -} - - -void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { - if (JvmtiExport::can_pop_frame()) { - Label L; - // Initiate popframe handling only if it is not already being processed. If the flag - // has the popframe_processing bit set, it means that this code is called *during* popframe - // handling - we don't want to reenter. - Register pop_cond = java_thread; // Not clear if any other register is available... - movl(pop_cond, Address(java_thread, JavaThread::popframe_condition_offset())); - testl(pop_cond, JavaThread::popframe_pending_bit); - jcc(Assembler::zero, L); - testl(pop_cond, JavaThread::popframe_processing_bit); - jcc(Assembler::notZero, L); - // Call Interpreter::remove_activation_preserving_args_entry() to get the - // address of the same-named entrypoint in the generated interpreter code. - call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); - jmp(rax); - bind(L); - get_thread(java_thread); - } -} - - -void InterpreterMacroAssembler::load_earlyret_value(TosState state) { - get_thread(rcx); - movl(rcx, Address(rcx, JavaThread::jvmti_thread_state_offset())); - const Address tos_addr (rcx, JvmtiThreadState::earlyret_tos_offset()); - const Address oop_addr (rcx, JvmtiThreadState::earlyret_oop_offset()); - const Address val_addr (rcx, JvmtiThreadState::earlyret_value_offset()); - const Address val_addr1(rcx, JvmtiThreadState::earlyret_value_offset() - + in_ByteSize(wordSize)); - switch (state) { - case atos: movptr(rax, oop_addr); - movptr(oop_addr, NULL_WORD); - verify_oop(rax, state); break; - case ltos: - movl(rdx, val_addr1); // fall through - case btos: // fall through - case ctos: // fall through - case stos: // fall through - case itos: movl(rax, val_addr); break; - case ftos: fld_s(val_addr); break; - case dtos: fld_d(val_addr); break; - case vtos: /* nothing to do */ break; - default : ShouldNotReachHere(); - } - // Clean up tos value in the thread object - movl(tos_addr, (int32_t) ilgl); - movptr(val_addr, NULL_WORD); - NOT_LP64(movptr(val_addr1, NULL_WORD)); -} - - -void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { - if (JvmtiExport::can_force_early_return()) { - Label L; - Register tmp = java_thread; - movptr(tmp, Address(tmp, JavaThread::jvmti_thread_state_offset())); - testptr(tmp, tmp); - jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; - - // Initiate earlyret handling only if it is not already being processed. - // If the flag has the earlyret_processing bit set, it means that this code - // is called *during* earlyret handling - we don't want to reenter. - movl(tmp, Address(tmp, JvmtiThreadState::earlyret_state_offset())); - cmpl(tmp, JvmtiThreadState::earlyret_pending); - jcc(Assembler::notEqual, L); - - // Call Interpreter::remove_activation_early_entry() to get the address of the - // same-named entrypoint in the generated interpreter code. - get_thread(java_thread); - movptr(tmp, Address(java_thread, JavaThread::jvmti_thread_state_offset())); - pushl(Address(tmp, JvmtiThreadState::earlyret_tos_offset())); - call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), 1); - jmp(rax); - bind(L); - get_thread(java_thread); - } -} - - -void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { - assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); - load_unsigned_short(reg, Address(rsi, bcp_offset)); - bswapl(reg); - shrl(reg, 16); -} - - -void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_offset, size_t index_size) { - assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); - if (index_size == sizeof(u2)) { - load_unsigned_short(reg, Address(rsi, bcp_offset)); - } else if (index_size == sizeof(u4)) { - movl(reg, Address(rsi, bcp_offset)); - // Check if the secondary index definition is still ~x, otherwise - // we have to change the following assembler code to calculate the - // plain index. - assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); - notl(reg); // convert to plain index - } else if (index_size == sizeof(u1)) { - load_unsigned_byte(reg, Address(rsi, bcp_offset)); - } else { - ShouldNotReachHere(); - } -} - - -void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, - int bcp_offset, size_t index_size) { - assert_different_registers(cache, index); - get_cache_index_at_bcp(index, bcp_offset, index_size); - movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); - assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); - assert(exact_log2(in_words(ConstantPoolCacheEntry::size())) == 2, "else change next line"); - shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index -} - - -void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache, - Register index, - Register bytecode, - int byte_no, - int bcp_offset, - size_t index_size) { - get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size); - movptr(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset())); - const int shift_count = (1 + byte_no) * BitsPerByte; - assert((byte_no == TemplateTable::f1_byte && shift_count == ConstantPoolCacheEntry::bytecode_1_shift) || - (byte_no == TemplateTable::f2_byte && shift_count == ConstantPoolCacheEntry::bytecode_2_shift), - "correct shift count"); - shrptr(bytecode, shift_count); - assert(ConstantPoolCacheEntry::bytecode_1_mask == ConstantPoolCacheEntry::bytecode_2_mask, "common mask"); - andptr(bytecode, ConstantPoolCacheEntry::bytecode_1_mask); -} - - -void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, - int bcp_offset, size_t index_size) { - assert(cache != tmp, "must use different register"); - get_cache_index_at_bcp(tmp, bcp_offset, index_size); - assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); - // convert from field index to ConstantPoolCacheEntry index - // and from word offset to byte offset - assert(exact_log2(in_bytes(ConstantPoolCacheEntry::size_in_bytes())) == 2 + LogBytesPerWord, "else change next line"); - shll(tmp, 2 + LogBytesPerWord); - movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); - // skip past the header - addptr(cache, in_bytes(ConstantPoolCache::base_offset())); - addptr(cache, tmp); // construct pointer to cache entry -} - -// Load object from cpool->resolved_references(index) -void InterpreterMacroAssembler::load_resolved_reference_at_index( - Register result, Register index) { - assert_different_registers(result, index); - // convert from field index to resolved_references() index and from - // word index to byte offset. Since this is a java object, it can be compressed - Register tmp = index; // reuse - shll(tmp, LogBytesPerHeapOop); - - get_constant_pool(result); - // load pointer for resolved_references[] objArray - movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); - // JNIHandles::resolve(obj); - movptr(result, Address(result, 0)); - // Add in the index - addptr(result, tmp); - load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); -} - - // Generate a subtype check: branch to ok_is_subtype if sub_klass is - // a subtype of super_klass. EAX holds the super_klass. Blows ECX. - // Resets EDI to locals. Register sub_klass cannot be any of the above. -void InterpreterMacroAssembler::gen_subtype_check( Register Rsub_klass, Label &ok_is_subtype ) { - assert( Rsub_klass != rax, "rax, holds superklass" ); - assert( Rsub_klass != rcx, "used as a temp" ); - assert( Rsub_klass != rdi, "used as a temp, restored from locals" ); - - // Profile the not-null value's klass. - profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, reloads rdi - - // Do the check. - check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx - - // Profile the failure of the check. - profile_typecheck_failed(rcx); // blows rcx -} - -void InterpreterMacroAssembler::f2ieee() { - if (IEEEPrecision) { - fstp_s(Address(rsp, 0)); - fld_s(Address(rsp, 0)); - } -} - - -void InterpreterMacroAssembler::d2ieee() { - if (IEEEPrecision) { - fstp_d(Address(rsp, 0)); - fld_d(Address(rsp, 0)); - } -} - -// Java Expression Stack - -void InterpreterMacroAssembler::pop_ptr(Register r) { - pop(r); -} - -void InterpreterMacroAssembler::pop_i(Register r) { - pop(r); -} - -void InterpreterMacroAssembler::pop_l(Register lo, Register hi) { - pop(lo); - pop(hi); -} - -void InterpreterMacroAssembler::pop_f() { - fld_s(Address(rsp, 0)); - addptr(rsp, 1 * wordSize); -} - -void InterpreterMacroAssembler::pop_d() { - fld_d(Address(rsp, 0)); - addptr(rsp, 2 * wordSize); -} - - -void InterpreterMacroAssembler::pop(TosState state) { - switch (state) { - case atos: pop_ptr(rax); break; - case btos: // fall through - case ctos: // fall through - case stos: // fall through - case itos: pop_i(rax); break; - case ltos: pop_l(rax, rdx); break; - case ftos: pop_f(); break; - case dtos: pop_d(); break; - case vtos: /* nothing to do */ break; - default : ShouldNotReachHere(); - } - verify_oop(rax, state); -} - -void InterpreterMacroAssembler::push_ptr(Register r) { - push(r); -} - -void InterpreterMacroAssembler::push_i(Register r) { - push(r); -} - -void InterpreterMacroAssembler::push_l(Register lo, Register hi) { - push(hi); - push(lo); -} - -void InterpreterMacroAssembler::push_f() { - // Do not schedule for no AGI! Never write beyond rsp! - subptr(rsp, 1 * wordSize); - fstp_s(Address(rsp, 0)); -} - -void InterpreterMacroAssembler::push_d(Register r) { - // Do not schedule for no AGI! Never write beyond rsp! - subptr(rsp, 2 * wordSize); - fstp_d(Address(rsp, 0)); -} - - -void InterpreterMacroAssembler::push(TosState state) { - verify_oop(rax, state); - switch (state) { - case atos: push_ptr(rax); break; - case btos: // fall through - case ctos: // fall through - case stos: // fall through - case itos: push_i(rax); break; - case ltos: push_l(rax, rdx); break; - case ftos: push_f(); break; - case dtos: push_d(rax); break; - case vtos: /* nothing to do */ break; - default : ShouldNotReachHere(); - } -} - - -// Helpers for swap and dup -void InterpreterMacroAssembler::load_ptr(int n, Register val) { - movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); -} - -void InterpreterMacroAssembler::store_ptr(int n, Register val) { - movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); -} - -void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { - // set sender sp - lea(rsi, Address(rsp, wordSize)); - // record last_sp - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi); -} - - -// Jump to from_interpreted entry of a call unless single stepping is possible -// in this thread in which case we must call the i2i entry -void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { - prepare_to_jump_from_interpreted(); - - if (JvmtiExport::can_post_interpreter_events()) { - Label run_compiled_code; - // JVMTI events, such as single-stepping, are implemented partly by avoiding running - // compiled code in threads for which the event is enabled. Check here for - // interp_only_mode if these events CAN be enabled. - get_thread(temp); - // interp_only is an int, on little endian it is sufficient to test the byte only - // Is a cmpl faster? - cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0); - jccb(Assembler::zero, run_compiled_code); - jmp(Address(method, Method::interpreter_entry_offset())); - bind(run_compiled_code); - } - - jmp(Address(method, Method::from_interpreted_offset())); - -} - - -// The following two routines provide a hook so that an implementation -// can schedule the dispatch in two parts. Intel does not do this. -void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { - // Nothing Intel-specific to be done here. -} - -void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { - dispatch_next(state, step); -} - -void InterpreterMacroAssembler::dispatch_base(TosState state, address* table, - bool verifyoop) { - verify_FPU(1, state); - if (VerifyActivationFrameSize) { - Label L; - mov(rcx, rbp); - subptr(rcx, rsp); - int min_frame_size = (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * wordSize; - cmpptr(rcx, min_frame_size); - jcc(Assembler::greaterEqual, L); - stop("broken stack frame"); - bind(L); - } - if (verifyoop) verify_oop(rax, state); - Address index(noreg, rbx, Address::times_ptr); - ExternalAddress tbl((address)table); - ArrayAddress dispatch(tbl, index); - jump(dispatch); -} - - -void InterpreterMacroAssembler::dispatch_only(TosState state) { - dispatch_base(state, Interpreter::dispatch_table(state)); -} - - -void InterpreterMacroAssembler::dispatch_only_normal(TosState state) { - dispatch_base(state, Interpreter::normal_table(state)); -} - -void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) { - dispatch_base(state, Interpreter::normal_table(state), false); -} - - -void InterpreterMacroAssembler::dispatch_next(TosState state, int step) { - // load next bytecode (load before advancing rsi to prevent AGI) - load_unsigned_byte(rbx, Address(rsi, step)); - // advance rsi - increment(rsi, step); - dispatch_base(state, Interpreter::dispatch_table(state)); -} - - -void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { - // load current bytecode - load_unsigned_byte(rbx, Address(rsi, 0)); - dispatch_base(state, table); -} - -// remove activation -// -// Unlock the receiver if this is a synchronized method. -// Unlock any Java monitors from syncronized blocks. -// Remove the activation from the stack. -// -// If there are locked Java monitors -// If throw_monitor_exception -// throws IllegalMonitorStateException -// Else if install_monitor_exception -// installs IllegalMonitorStateException -// Else -// no error processing -void InterpreterMacroAssembler::remove_activation(TosState state, Register ret_addr, - bool throw_monitor_exception, - bool install_monitor_exception, - bool notify_jvmdi) { - // Note: Registers rax, rdx and FPU ST(0) may be in use for the result - // check if synchronized method - Label unlocked, unlock, no_unlock; - - get_thread(rcx); - const Address do_not_unlock_if_synchronized(rcx, - in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); - - movbool(rbx, do_not_unlock_if_synchronized); - mov(rdi,rbx); - movbool(do_not_unlock_if_synchronized, false); // reset the flag - - movptr(rbx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); // get method access flags - movl(rcx, Address(rbx, Method::access_flags_offset())); - - testl(rcx, JVM_ACC_SYNCHRONIZED); - jcc(Assembler::zero, unlocked); - - // Don't unlock anything if the _do_not_unlock_if_synchronized flag - // is set. - mov(rcx,rdi); - testbool(rcx); - jcc(Assembler::notZero, no_unlock); - - // unlock monitor - push(state); // save result - - // BasicObjectLock will be first in list, since this is a synchronized method. However, need - // to check that the object has not been unlocked by an explicit monitorexit bytecode. - const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); - lea (rdx, monitor); // address of first monitor - - movptr (rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); - testptr(rax, rax); - jcc (Assembler::notZero, unlock); - - pop(state); - if (throw_monitor_exception) { - empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow - - // Entry already unlocked, need to throw exception - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); - should_not_reach_here(); - } else { - // Monitor already unlocked during a stack unroll. - // If requested, install an illegal_monitor_state_exception. - // Continue with stack unrolling. - if (install_monitor_exception) { - empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); - } - jmp(unlocked); - } - - bind(unlock); - unlock_object(rdx); - pop(state); - - // Check that for block-structured locking (i.e., that all locked objects has been unlocked) - bind(unlocked); - - // rax, rdx: Might contain return value - - // Check that all monitors are unlocked - { - Label loop, exception, entry, restart; - const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; - 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); - - bind(restart); - 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 - jmp(entry); - - // Entry already locked, need to throw exception - bind(exception); - - if (throw_monitor_exception) { - empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow - - // Throw exception - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); - should_not_reach_here(); - } else { - // Stack unrolling. Unlock object and install illegal_monitor_exception - // Unlock does not block, so don't have to worry about the frame - - push(state); - mov(rdx, rcx); - unlock_object(rdx); - pop(state); - - if (install_monitor_exception) { - empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); - } - - jmp(restart); - } - - bind(loop); - cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used - jcc(Assembler::notEqual, exception); - - 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(no_unlock); - - // jvmti support - if (notify_jvmdi) { - notify_method_exit(state, NotifyJVMTI); // preserve TOSCA - } else { - notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA - } - - // remove activation - movptr(rbx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp - leave(); // remove frame anchor - pop(ret_addr); // get return address - mov(rsp, rbx); // set sp to sender sp - if (UseSSE) { - // float and double are returned in xmm register in SSE-mode - if (state == ftos && UseSSE >= 1) { - subptr(rsp, wordSize); - fstp_s(Address(rsp, 0)); - movflt(xmm0, Address(rsp, 0)); - addptr(rsp, wordSize); - } else if (state == dtos && UseSSE >= 2) { - subptr(rsp, 2*wordSize); - fstp_d(Address(rsp, 0)); - movdbl(xmm0, Address(rsp, 0)); - addptr(rsp, 2*wordSize); - } - } -} - -#endif /* !CC_INTERP */ - -void InterpreterMacroAssembler::get_method_counters(Register method, - Register mcs, Label& skip) { - Label has_counters; - movptr(mcs, Address(method, Method::method_counters_offset())); - testptr(mcs, mcs); - jcc(Assembler::notZero, has_counters); - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::build_method_counters), method); - movptr(mcs, Address(method,Method::method_counters_offset())); - testptr(mcs, mcs); - jcc(Assembler::zero, skip); // No MethodCounters allocated, OutOfMemory - bind(has_counters); -} - - -// Lock object -// -// Argument: rdx : Points to BasicObjectLock to be used for locking. Must -// be initialized with object to lock -void InterpreterMacroAssembler::lock_object(Register lock_reg) { - assert(lock_reg == rdx, "The argument is only for looks. It must be rdx"); - - if (UseHeavyMonitors) { - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); - } else { - - Label done; - - const Register swap_reg = rax; // Must use rax, for cmpxchg instruction - const Register obj_reg = rcx; // Will contain the oop - - const int obj_offset = BasicObjectLock::obj_offset_in_bytes(); - const int lock_offset = BasicObjectLock::lock_offset_in_bytes (); - const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes(); - - Label slow_case; - - // Load object pointer into obj_reg %rcx - movptr(obj_reg, Address(lock_reg, obj_offset)); - - if (UseBiasedLocking) { - // Note: we use noreg for the temporary register since it's hard - // to come up with a free register on all incoming code paths - biased_locking_enter(lock_reg, obj_reg, swap_reg, noreg, false, done, &slow_case); - } - - // Load immediate 1 into swap_reg %rax, - movptr(swap_reg, (int32_t)1); - - // Load (object->mark() | 1) into swap_reg %rax, - orptr(swap_reg, Address(obj_reg, 0)); - - // Save (object->mark() | 1) into BasicLock's displaced header - movptr(Address(lock_reg, mark_offset), swap_reg); - - assert(lock_offset == 0, "displached header must be first word in BasicObjectLock"); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(lock_reg, Address(obj_reg, 0)); - if (PrintBiasedLockingStatistics) { - cond_inc32(Assembler::zero, - ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); - } - jcc(Assembler::zero, done); - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) rsp <= mark < mark + os::pagesize() - // - // These 3 tests can be done by evaluating the following - // expression: ((mark - rsp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg - subptr(swap_reg, rsp); - andptr(swap_reg, 3 - os::vm_page_size()); - - // Save the test result, for recursive case, the result is zero - movptr(Address(lock_reg, mark_offset), swap_reg); - - if (PrintBiasedLockingStatistics) { - cond_inc32(Assembler::zero, - ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); - } - jcc(Assembler::zero, done); - - bind(slow_case); - - // Call the runtime routine for slow case - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); - - bind(done); - } -} - - -// Unlocks an object. Used in monitorexit bytecode and remove_activation. -// -// Argument: rdx : Points to BasicObjectLock structure for lock -// Throw an IllegalMonitorException if object is not locked by current thread -// -// Uses: rax, rbx, rcx, rdx -void InterpreterMacroAssembler::unlock_object(Register lock_reg) { - assert(lock_reg == rdx, "The argument is only for looks. It must be rdx"); - - if (UseHeavyMonitors) { - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); - } else { - Label done; - - const Register swap_reg = rax; // Must use rax, for cmpxchg instruction - const Register header_reg = rbx; // Will contain the old oopMark - const Register obj_reg = rcx; // Will contain the oop - - save_bcp(); // Save in case of exception - - // Convert from BasicObjectLock structure to object and BasicLock structure - // Store the BasicLock address into %rax, - lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); - - // Load oop into obj_reg(%rcx) - movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes ())); - - // Free entry - movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); - - if (UseBiasedLocking) { - biased_locking_exit(obj_reg, header_reg, done); - } - - // Load the old header from BasicLock structure - movptr(header_reg, Address(swap_reg, BasicLock::displaced_header_offset_in_bytes())); - - // Test for recursion - testptr(header_reg, header_reg); - - // zero for recursive case - jcc(Assembler::zero, done); - - // Atomic swap back the old header - if (os::is_MP()) lock(); - cmpxchgptr(header_reg, Address(obj_reg, 0)); - - // zero for recursive case - jcc(Assembler::zero, done); - - // Call the runtime routine for slow case. - movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), obj_reg); // restore obj - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); - - bind(done); - - restore_bcp(); - } -} - - -#ifndef CC_INTERP - -// Test ImethodDataPtr. If it is null, continue at the specified label -void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, Label& zero_continue) { - assert(ProfileInterpreter, "must be profiling interpreter"); - movptr(mdp, Address(rbp, frame::interpreter_frame_mdp_offset * wordSize)); - testptr(mdp, mdp); - jcc(Assembler::zero, zero_continue); -} - - -// Set the method data pointer for the current bcp. -void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { - assert(ProfileInterpreter, "must be profiling interpreter"); - Label set_mdp; - push(rax); - push(rbx); - - get_method(rbx); - // Test MDO to avoid the call if it is NULL. - movptr(rax, Address(rbx, in_bytes(Method::method_data_offset()))); - testptr(rax, rax); - jcc(Assembler::zero, set_mdp); - // rbx,: method - // rsi: bcp - call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi); - // rax,: mdi - // mdo is guaranteed to be non-zero here, we checked for it before the call. - movptr(rbx, Address(rbx, in_bytes(Method::method_data_offset()))); - addptr(rbx, in_bytes(MethodData::data_offset())); - addptr(rax, rbx); - bind(set_mdp); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), rax); - pop(rbx); - pop(rax); -} - -void InterpreterMacroAssembler::verify_method_data_pointer() { - assert(ProfileInterpreter, "must be profiling interpreter"); -#ifdef ASSERT - Label verify_continue; - push(rax); - push(rbx); - push(rcx); - push(rdx); - test_method_data_pointer(rcx, verify_continue); // If mdp is zero, continue - get_method(rbx); - - // If the mdp is valid, it will point to a DataLayout header which is - // consistent with the bcp. The converse is highly probable also. - load_unsigned_short(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); - addptr(rdx, Address(rbx, Method::const_offset())); - lea(rdx, Address(rdx, ConstMethod::codes_offset())); - cmpptr(rdx, rsi); - jcc(Assembler::equal, verify_continue); - // rbx,: method - // rsi: bcp - // rcx: mdp - call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), rbx, rsi, rcx); - bind(verify_continue); - pop(rdx); - pop(rcx); - pop(rbx); - pop(rax); -#endif // ASSERT -} - - -void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, int constant, Register value) { - // %%% this seems to be used to store counter data which is surely 32bits - // however 64bit side stores 64 bits which seems wrong - assert(ProfileInterpreter, "must be profiling interpreter"); - Address data(mdp_in, constant); - movptr(data, value); -} - - -void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, - int constant, - bool decrement) { - // Counter address - Address data(mdp_in, constant); - - increment_mdp_data_at(data, decrement); -} - - -void InterpreterMacroAssembler::increment_mdp_data_at(Address data, - bool decrement) { - - assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); - assert(ProfileInterpreter, "must be profiling interpreter"); - - // %%% 64bit treats this as 64 bit which seems unlikely - if (decrement) { - // Decrement the register. Set condition codes. - addl(data, -DataLayout::counter_increment); - // If the decrement causes the counter to overflow, stay negative - Label L; - jcc(Assembler::negative, L); - addl(data, DataLayout::counter_increment); - bind(L); - } else { - assert(DataLayout::counter_increment == 1, - "flow-free idiom only works with 1"); - // Increment the register. Set carry flag. - addl(data, DataLayout::counter_increment); - // If the increment causes the counter to overflow, pull back by 1. - sbbl(data, 0); - } -} - - -void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, - Register reg, - int constant, - bool decrement) { - Address data(mdp_in, reg, Address::times_1, constant); - - increment_mdp_data_at(data, decrement); -} - - -void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, int flag_byte_constant) { - assert(ProfileInterpreter, "must be profiling interpreter"); - int header_offset = in_bytes(DataLayout::header_offset()); - int header_bits = DataLayout::flag_mask_to_header_mask(flag_byte_constant); - // Set the flag - orl(Address(mdp_in, header_offset), header_bits); -} - - - -void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, - int offset, - Register value, - Register test_value_out, - Label& not_equal_continue) { - assert(ProfileInterpreter, "must be profiling interpreter"); - if (test_value_out == noreg) { - cmpptr(value, Address(mdp_in, offset)); - } else { - // Put the test value into a register, so caller can use it: - movptr(test_value_out, Address(mdp_in, offset)); - cmpptr(test_value_out, value); - } - jcc(Assembler::notEqual, not_equal_continue); -} - - -void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, int offset_of_disp) { - assert(ProfileInterpreter, "must be profiling interpreter"); - Address disp_address(mdp_in, offset_of_disp); - addptr(mdp_in,disp_address); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); -} - - -void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp) { - assert(ProfileInterpreter, "must be profiling interpreter"); - Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); - addptr(mdp_in, disp_address); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); -} - - -void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, int constant) { - assert(ProfileInterpreter, "must be profiling interpreter"); - addptr(mdp_in, constant); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); -} - - -void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { - assert(ProfileInterpreter, "must be profiling interpreter"); - push(return_bci); // save/restore across call_VM - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); - pop(return_bci); -} - - -void InterpreterMacroAssembler::profile_taken_branch(Register mdp, Register bumped_count) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - // Otherwise, assign to mdp - test_method_data_pointer(mdp, profile_continue); - - // We are taking a branch. Increment the taken count. - // We inline increment_mdp_data_at to return bumped_count in a register - //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); - Address data(mdp, in_bytes(JumpData::taken_offset())); - - // %%% 64bit treats these cells as 64 bit but they seem to be 32 bit - movl(bumped_count,data); - assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); - addl(bumped_count, DataLayout::counter_increment); - sbbl(bumped_count, 0); - movl(data,bumped_count); // Store back out - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // We are taking a branch. Increment the not taken count. - increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); - - // The method data pointer needs to be updated to correspond to the next bytecode - update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); - bind (profile_continue); - } -} - -void InterpreterMacroAssembler::profile_call(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // We are making a call. Increment the count. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_final_call(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // We are making a call. Increment the count. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, - Register reg2, - bool receiver_can_be_null) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - testptr(receiver, receiver); - jccb(Assembler::notZero, not_null); - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - jmp(skip_receiver_profile); - bind(not_null); - } - - // Record the receiver type. - record_klass_in_profile(receiver, mdp, reg2, true); - bind(skip_receiver_profile); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, - in_bytes(VirtualCallData:: - virtual_call_data_size())); - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::record_klass_in_profile_helper( - Register receiver, Register mdp, - Register reg2, int start_row, - Label& done, bool is_virtual_call) { - if (TypeProfileWidth == 0) { - if (is_virtual_call) { - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - } - return; - } - - int last_row = VirtualCallData::row_limit() - 1; - assert(start_row <= last_row, "must be work left to do"); - // Test this row for both the receiver and for null. - // Take any of three different outcomes: - // 1. found receiver => increment count and goto done - // 2. found null => keep looking for case 1, maybe allocate this cell - // 3. found something else => keep looking for cases 1 and 2 - // Case 3 is handled by a recursive call. - for (int row = start_row; row <= last_row; row++) { - Label next_test; - bool test_for_null_also = (row == start_row); - - // See if the receiver is receiver[n]. - int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); - test_mdp_data_at(mdp, recvr_offset, receiver, - (test_for_null_also ? reg2 : noreg), - next_test); - // (Reg2 now contains the receiver from the CallData.) - - // The receiver is receiver[n]. Increment count[n]. - int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); - increment_mdp_data_at(mdp, count_offset); - jmp(done); - bind(next_test); - - if (row == start_row) { - Label found_null; - // Failed the equality check on receiver[n]... Test for null. - testptr(reg2, reg2); - if (start_row == last_row) { - // The only thing left to do is handle the null case. - if (is_virtual_call) { - jccb(Assembler::zero, found_null); - // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polymorphic case. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - jmp(done); - bind(found_null); - } else { - jcc(Assembler::notZero, done); - } - break; - } - // Since null is rare, make it be the branch-taken case. - jcc(Assembler::zero, found_null); - - // Put all the "Case 3" tests here. - record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); - - // Found a null. Keep searching for a matching receiver, - // but remember that this is an empty (unused) slot. - bind(found_null); - } - } - - // In the fall-through case, we found no matching receiver, but we - // observed the receiver[start_row] is NULL. - - // Fill in the receiver field and increment the count. - int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); - set_mdp_data_at(mdp, recvr_offset, receiver); - int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); - movptr(reg2, (intptr_t)DataLayout::counter_increment); - set_mdp_data_at(mdp, count_offset, reg2); - if (start_row > 0) { - jmp(done); - } -} - -void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, - Register mdp, Register reg2, - bool is_virtual_call) { - assert(ProfileInterpreter, "must be profiling"); - Label done; - - record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); - - bind (done); -} - -void InterpreterMacroAssembler::profile_ret(Register return_bci, Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - uint row; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // Update the total ret count. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - - for (row = 0; row < RetData::row_limit(); row++) { - Label next_test; - - // See if return_bci is equal to bci[n]: - test_mdp_data_at(mdp, in_bytes(RetData::bci_offset(row)), return_bci, - noreg, next_test); - - // return_bci is equal to bci[n]. Increment the count. - increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_offset(mdp, in_bytes(RetData::bci_displacement_offset(row))); - jmp(profile_continue); - bind(next_test); - } - - update_mdp_for_ret(return_bci); - - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_null_seen(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); - - // The method data pointer needs to be updated. - int mdp_delta = in_bytes(BitData::bit_data_size()); - if (TypeProfileCasts) { - mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); - } - update_mdp_by_constant(mdp, mdp_delta); - - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { - if (ProfileInterpreter && TypeProfileCasts) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - int count_offset = in_bytes(CounterData::count_offset()); - // Back up the address, since we have already bumped the mdp. - count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); - - // *Decrement* the counter. We expect to see zero or small negatives. - increment_mdp_data_at(mdp, count_offset, true); - - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) -{ - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // The method data pointer needs to be updated. - int mdp_delta = in_bytes(BitData::bit_data_size()); - if (TypeProfileCasts) { - mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); - - // Record the object type. - record_klass_in_profile(klass, mdp, reg2, false); - assert(reg2 == rdi, "we know how to fix this blown reg"); - restore_locals(); // Restore EDI - } - update_mdp_by_constant(mdp, mdp_delta); - - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_switch_default(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // Update the default case count - increment_mdp_data_at(mdp, in_bytes(MultiBranchData::default_count_offset())); - - // The method data pointer needs to be updated. - update_mdp_by_offset(mdp, in_bytes(MultiBranchData::default_displacement_offset())); - - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_switch_case(Register index, Register mdp, Register reg2) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() - movptr(reg2, (intptr_t)in_bytes(MultiBranchData::per_case_size())); - // index is positive and so should have correct value if this code were - // used on 64bits - imulptr(index, reg2); - addptr(index, in_bytes(MultiBranchData::case_array_offset())); - - // Update the case count - increment_mdp_data_at(mdp, index, in_bytes(MultiBranchData::relative_count_offset())); - - // The method data pointer needs to be updated. - update_mdp_by_offset(mdp, index, in_bytes(MultiBranchData::relative_displacement_offset())); - - bind (profile_continue); - } -} - -#endif // !CC_INTERP - - - -void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { - if (state == atos) MacroAssembler::verify_oop(reg); -} - - -#ifndef CC_INTERP -void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { - if (state == ftos || state == dtos) MacroAssembler::verify_FPU(stack_depth); -} - -// Jump if ((*counter_addr += increment) & mask) satisfies the condition. -void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, - int increment, Address mask, - Register scratch, bool preloaded, - Condition cond, Label* where) { - if (!preloaded) { - movl(scratch, counter_addr); - } - incrementl(scratch, increment); - movl(counter_addr, scratch); - andl(scratch, mask); - jcc(cond, *where); -} -#endif /* CC_INTERP */ - - -void InterpreterMacroAssembler::notify_method_entry() { - // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to - // track stack depth. If it is possible to enter interp_only_mode we add - // the code to check if the event should be sent. - if (JvmtiExport::can_post_interpreter_events()) { - Label L; - get_thread(rcx); - movl(rcx, Address(rcx, JavaThread::interp_only_mode_offset())); - testl(rcx,rcx); - jcc(Assembler::zero, L); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry)); - bind(L); - } - - { - SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); - get_thread(rcx); - get_method(rbx); - call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), rcx, rbx); - } - - // RedefineClasses() tracing support for obsolete method entry - if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { - get_thread(rcx); - get_method(rbx); - call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), - rcx, rbx); - } -} - - -void InterpreterMacroAssembler::notify_method_exit( - TosState state, NotifyMethodExitMode mode) { - // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to - // track stack depth. If it is possible to enter interp_only_mode we add - // the code to check if the event should be sent. - if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { - Label L; - // Note: frame::interpreter_frame_result has a dependency on how the - // method result is saved across the call to post_method_exit. If this - // is changed then the interpreter_frame_result implementation will - // need to be updated too. - - // For c++ interpreter the result is always stored at a known location in the frame - // template interpreter will leave it on the top of the stack. - NOT_CC_INTERP(push(state);) - get_thread(rcx); - movl(rcx, Address(rcx, JavaThread::interp_only_mode_offset())); - testl(rcx,rcx); - jcc(Assembler::zero, L); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); - bind(L); - NOT_CC_INTERP(pop(state);) - } - - { - SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); - NOT_CC_INTERP(push(state)); - get_thread(rbx); - get_method(rcx); - call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), - rbx, rcx); - NOT_CC_INTERP(pop(state)); - } -} diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Tue Mar 31 16:22:59 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +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. - * - */ - -#ifndef CC_INTERP - protected: - // Interpreter specific version of call_VM_base - virtual void call_VM_leaf_base( - address entry_point, - int number_of_arguments - ); - - virtual void call_VM_base( - Register oop_result, - Register java_thread, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions - ); - - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - - // base routine for all dispatches - void dispatch_base(TosState state, address* table, bool verifyoop = true); -#endif /* CC_INTERP */ - - public: - InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(rdi), _bcp_register(rsi) {} - - void load_earlyret_value(TosState state); - - // Interpreter-specific registers -#ifdef CC_INTERP - void save_bcp() { /* not needed in c++ interpreter and harmless */ } - void restore_bcp() { /* not needed in c++ interpreter and harmless */ } - - // Helpers for runtime call arguments/results - void get_method(Register reg); - -#else - - void save_bcp() { movptr(Address(rbp, frame::interpreter_frame_bcp_offset * wordSize), rsi); } - void restore_bcp() { movptr(rsi, Address(rbp, frame::interpreter_frame_bcp_offset * wordSize)); } - void restore_locals() { movptr(rdi, Address(rbp, frame::interpreter_frame_locals_offset * wordSize)); } - - // Helpers for runtime call arguments/results - void get_method(Register reg) { movptr(reg, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); } - void get_const(Register reg) { get_method(reg); movptr(reg, Address(reg, Method::const_offset())); } - void get_constant_pool(Register reg) { get_const(reg); movptr(reg, Address(reg, ConstMethod::constants_offset())); } - void get_constant_pool_cache(Register reg) { get_constant_pool(reg); movptr(reg, Address(reg, ConstantPool::cache_offset_in_bytes())); } - void get_cpool_and_tags(Register cpool, Register tags) { get_constant_pool(cpool); movptr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes())); - } - void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); - void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); - void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); - void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); - void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); - - // load cpool->resolved_references(index); - void load_resolved_reference_at_index(Register result, Register index); - - // Expression stack - void f2ieee(); // truncate ftos to 32bits - void d2ieee(); // truncate dtos to 64bits - - void pop_ptr(Register r = rax); - void pop_i(Register r = rax); - void pop_l(Register lo = rax, Register hi = rdx); - void pop_f(); - void pop_d(); - - void push_ptr(Register r = rax); - void push_i(Register r = rax); - void push_l(Register lo = rax, Register hi = rdx); - void push_d(Register r = rax); - void push_f(); - - void pop(TosState state); // transition vtos -> state - void push(TosState state); // transition state -> vtos - - void pop(Register r ) { ((MacroAssembler*)this)->pop(r); } - - void push(Register r ) { ((MacroAssembler*)this)->push(r); } - void push(int32_t imm ) { ((MacroAssembler*)this)->push(imm); } - - // These are dummies to prevent surprise implicit conversions to Register - void pop(void* v ); // Add unimplemented ambiguous method - void push(void* v ); // Add unimplemented ambiguous method - - void empty_expression_stack() { - movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); - // NULL last_sp until next java call - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); - } - - // Helpers for swap and dup - void load_ptr(int n, Register val); - void store_ptr(int n, Register val); - - // Generate a subtype check: branch to ok_is_subtype if sub_klass is - // a subtype of super_klass. EAX holds the super_klass. Blows ECX - // and EDI. Register sub_klass cannot be any of the above. - void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); - - // Dispatching - void dispatch_prolog(TosState state, int step = 0); - void dispatch_epilog(TosState state, int step = 0); - void dispatch_only(TosState state); // dispatch via rbx, (assume rbx, is loaded already) - void dispatch_only_normal(TosState state); // dispatch normal table via rbx, (assume rbx, is loaded already) - void dispatch_only_noverify(TosState state); - void dispatch_next(TosState state, int step = 0); // load rbx, from [esi + step] and dispatch via rbx, - void dispatch_via (TosState state, address* table); // load rbx, from [esi] and dispatch via rbx, and table - - - // jump to an invoked target - void prepare_to_jump_from_interpreted(); - void jump_from_interpreted(Register method, Register temp); - - // Returning from interpreted functions - // - // Removes the current activation (incl. unlocking of monitors) - // and sets up the return address. This code is also used for - // exception unwindwing. In that case, we do not want to throw - // IllegalMonitorStateExceptions, since that might get us into an - // infinite rethrow exception loop. - // Additionally this code is used for popFrame and earlyReturn. - // In popFrame case we want to skip throwing an exception, - // installing an exception, and notifying jvmdi. - // In earlyReturn case we only want to skip throwing an exception - // and installing an exception. - void remove_activation(TosState state, Register ret_addr, - bool throw_monitor_exception = true, - bool install_monitor_exception = true, - bool notify_jvmdi = true); -#endif /* !CC_INTERP */ - void get_method_counters(Register method, Register mcs, Label& skip); - - // Debugging - void verify_oop(Register reg, TosState state = atos); // only if +VerifyOops && state == atos -#ifndef CC_INTERP - void verify_FPU(int stack_depth, TosState state = ftos); // only if +VerifyFPU && (state == ftos || state == dtos) - -#endif /* !CC_INTERP */ - - // Object locking - void lock_object (Register lock_reg); - void unlock_object(Register lock_reg); - -#ifndef CC_INTERP - - // Interpreter profiling operations - void set_method_data_pointer_for_bcp(); - void test_method_data_pointer(Register mdp, Label& zero_continue); - void verify_method_data_pointer(); - - void set_mdp_data_at(Register mdp_in, int constant, Register value); - void increment_mdp_data_at(Address data, bool decrement = false); - void increment_mdp_data_at(Register mdp_in, int constant, - bool decrement = false); - void increment_mdp_data_at(Register mdp_in, Register reg, int constant, - bool decrement = false); - void increment_mask_and_jump(Address counter_addr, - int increment, Address mask, - Register scratch, bool preloaded, - Condition cond, Label* where); - void set_mdp_flag_at(Register mdp_in, int flag_constant); - void test_mdp_data_at(Register mdp_in, int offset, Register value, - Register test_value_out, - Label& not_equal_continue); - - void record_klass_in_profile(Register receiver, Register mdp, - Register reg2, bool is_virtual_call); - void record_klass_in_profile_helper(Register receiver, Register mdp, - Register reg2, int start_row, - Label& done, bool is_virtual_call); - - void update_mdp_by_offset(Register mdp_in, int offset_of_offset); - void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); - void update_mdp_by_constant(Register mdp_in, int constant); - void update_mdp_for_ret(Register return_bci); - - void profile_taken_branch(Register mdp, Register bumped_count); - void profile_not_taken_branch(Register mdp); - void profile_call(Register mdp); - void profile_final_call(Register mdp); - void profile_virtual_call(Register receiver, Register mdp, Register scratch2, - bool receiver_can_be_null = false); - void profile_ret(Register return_bci, Register mdp); - void profile_null_seen(Register mdp); - void profile_typecheck(Register mdp, Register klass, Register scratch); - void profile_typecheck_failed(Register mdp); - void profile_switch_default(Register mdp); - void profile_switch_case(Register index_in_scratch, Register mdp, Register scratch2); - -#endif /* !CC_INTERP */ - - typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; - - // support for jvmti - void notify_method_entry(); - void notify_method_exit(TosState state, NotifyMethodExitMode mode); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Tue Mar 31 16:22:59 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1507 +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 "interp_masm_x86.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" -#include "oops/arrayOop.hpp" -#include "oops/markOop.hpp" -#include "oops/methodData.hpp" -#include "oops/method.hpp" -#include "prims/jvmtiExport.hpp" -#include "prims/jvmtiRedefineClassesTrace.hpp" -#include "prims/jvmtiThreadState.hpp" -#include "runtime/basicLock.hpp" -#include "runtime/biasedLocking.hpp" -#include "runtime/sharedRuntime.hpp" -#include "runtime/thread.inline.hpp" - - -// Implementation of InterpreterMacroAssembler - -#ifdef CC_INTERP -void InterpreterMacroAssembler::get_method(Register reg) { - movptr(reg, Address(rbp, -((int)sizeof(BytecodeInterpreter) + 2 * wordSize))); - movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); -} -#endif // CC_INTERP - -#ifndef CC_INTERP - -void InterpreterMacroAssembler::call_VM_leaf_base(address entry_point, - int number_of_arguments) { - // interpreter specific - // - // Note: No need to save/restore bcp & locals (r13 & r14) pointer - // since these are callee saved registers and no blocking/ - // GC can happen in leaf calls. - // Further Note: DO NOT save/restore bcp/locals. If a caller has - // already saved them so that it can use esi/edi as temporaries - // then a save/restore here will DESTROY the copy the caller - // saved! There used to be a save_bcp() that only happened in - // the ASSERT path (no restore_bcp). Which caused bizarre failures - // when jvm built with ASSERTs. -#ifdef ASSERT - { - Label L; - cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - jcc(Assembler::equal, L); - stop("InterpreterMacroAssembler::call_VM_leaf_base:" - " last_sp != NULL"); - bind(L); - } -#endif - // super call - MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); - // interpreter specific - // Used to ASSERT that r13/r14 were equal to frame's bcp/locals - // but since they may not have been saved (and we don't want to - // save thme here (see note above) the assert is invalid. -} - -void InterpreterMacroAssembler::call_VM_base(Register oop_result, - Register java_thread, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions) { - // interpreter specific - // - // Note: Could avoid restoring locals ptr (callee saved) - however doesn't - // really make a difference for these runtime calls, since they are - // slow anyway. Btw., bcp must be saved/restored since it may change - // due to GC. - // assert(java_thread == noreg , "not expecting a precomputed java thread"); - save_bcp(); -#ifdef ASSERT - { - Label L; - cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - jcc(Assembler::equal, L); - stop("InterpreterMacroAssembler::call_VM_leaf_base:" - " last_sp != NULL"); - bind(L); - } -#endif /* ASSERT */ - // super call - MacroAssembler::call_VM_base(oop_result, noreg, last_java_sp, - entry_point, number_of_arguments, - check_exceptions); - // interpreter specific - restore_bcp(); - restore_locals(); -} - - -void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { - if (JvmtiExport::can_pop_frame()) { - Label L; - // Initiate popframe handling only if it is not already being - // processed. If the flag has the popframe_processing bit set, it - // means that this code is called *during* popframe handling - we - // don't want to reenter. - // This method is only called just after the call into the vm in - // call_VM_base, so the arg registers are available. - movl(c_rarg0, Address(r15_thread, JavaThread::popframe_condition_offset())); - testl(c_rarg0, JavaThread::popframe_pending_bit); - jcc(Assembler::zero, L); - testl(c_rarg0, JavaThread::popframe_processing_bit); - jcc(Assembler::notZero, L); - // Call Interpreter::remove_activation_preserving_args_entry() to get the - // address of the same-named entrypoint in the generated interpreter code. - call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); - jmp(rax); - bind(L); - } -} - - -void InterpreterMacroAssembler::load_earlyret_value(TosState state) { - movptr(rcx, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); - const Address tos_addr(rcx, JvmtiThreadState::earlyret_tos_offset()); - const Address oop_addr(rcx, JvmtiThreadState::earlyret_oop_offset()); - const Address val_addr(rcx, JvmtiThreadState::earlyret_value_offset()); - switch (state) { - case atos: movptr(rax, oop_addr); - movptr(oop_addr, (int32_t)NULL_WORD); - verify_oop(rax, state); break; - case ltos: movptr(rax, val_addr); break; - case btos: // fall through - case ctos: // fall through - case stos: // fall through - case itos: movl(rax, val_addr); break; - case ftos: movflt(xmm0, val_addr); break; - case dtos: movdbl(xmm0, val_addr); break; - case vtos: /* nothing to do */ break; - default : ShouldNotReachHere(); - } - // Clean up tos value in the thread object - movl(tos_addr, (int) ilgl); - movl(val_addr, (int32_t) NULL_WORD); -} - - -void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { - if (JvmtiExport::can_force_early_return()) { - Label L; - movptr(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); - testptr(c_rarg0, c_rarg0); - jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; - - // Initiate earlyret handling only if it is not already being processed. - // If the flag has the earlyret_processing bit set, it means that this code - // is called *during* earlyret handling - we don't want to reenter. - movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_state_offset())); - cmpl(c_rarg0, JvmtiThreadState::earlyret_pending); - jcc(Assembler::notEqual, L); - - // Call Interpreter::remove_activation_early_entry() to get the address of the - // same-named entrypoint in the generated interpreter code. - movptr(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); - movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_tos_offset())); - call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), c_rarg0); - jmp(rax); - bind(L); - } -} - - -void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp( - Register reg, - int bcp_offset) { - assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); - load_unsigned_short(reg, Address(r13, bcp_offset)); - bswapl(reg); - shrl(reg, 16); -} - - -void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index, - int bcp_offset, - size_t index_size) { - assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); - if (index_size == sizeof(u2)) { - load_unsigned_short(index, Address(r13, bcp_offset)); - } else if (index_size == sizeof(u4)) { - movl(index, Address(r13, bcp_offset)); - // Check if the secondary index definition is still ~x, otherwise - // we have to change the following assembler code to calculate the - // plain index. - assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); - notl(index); // convert to plain index - } else if (index_size == sizeof(u1)) { - load_unsigned_byte(index, Address(r13, bcp_offset)); - } else { - ShouldNotReachHere(); - } -} - - -void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, - Register index, - int bcp_offset, - size_t index_size) { - assert_different_registers(cache, index); - get_cache_index_at_bcp(index, bcp_offset, index_size); - movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); - assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); - // convert from field index to ConstantPoolCacheEntry index - assert(exact_log2(in_words(ConstantPoolCacheEntry::size())) == 2, "else change next line"); - shll(index, 2); -} - - -void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache, - Register index, - Register bytecode, - int byte_no, - int bcp_offset, - size_t index_size) { - get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size); - // We use a 32-bit load here since the layout of 64-bit words on - // little-endian machines allow us that. - movl(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset())); - const int shift_count = (1 + byte_no) * BitsPerByte; - assert((byte_no == TemplateTable::f1_byte && shift_count == ConstantPoolCacheEntry::bytecode_1_shift) || - (byte_no == TemplateTable::f2_byte && shift_count == ConstantPoolCacheEntry::bytecode_2_shift), - "correct shift count"); - shrl(bytecode, shift_count); - assert(ConstantPoolCacheEntry::bytecode_1_mask == ConstantPoolCacheEntry::bytecode_2_mask, "common mask"); - andl(bytecode, ConstantPoolCacheEntry::bytecode_1_mask); -} - - -void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, - Register tmp, - int bcp_offset, - size_t index_size) { - assert(cache != tmp, "must use different register"); - get_cache_index_at_bcp(tmp, bcp_offset, index_size); - assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); - // convert from field index to ConstantPoolCacheEntry index - // and from word offset to byte offset - assert(exact_log2(in_bytes(ConstantPoolCacheEntry::size_in_bytes())) == 2 + LogBytesPerWord, "else change next line"); - shll(tmp, 2 + LogBytesPerWord); - movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); - // skip past the header - addptr(cache, in_bytes(ConstantPoolCache::base_offset())); - addptr(cache, tmp); // construct pointer to cache entry -} - -// Load object from cpool->resolved_references(index) -void InterpreterMacroAssembler::load_resolved_reference_at_index( - Register result, Register index) { - assert_different_registers(result, index); - // convert from field index to resolved_references() index and from - // word index to byte offset. Since this is a java object, it can be compressed - Register tmp = index; // reuse - shll(tmp, LogBytesPerHeapOop); - - get_constant_pool(result); - // load pointer for resolved_references[] objArray - movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); - // JNIHandles::resolve(obj); - movptr(result, Address(result, 0)); - // Add in the index - addptr(result, tmp); - load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); -} - -// Generate a subtype check: branch to ok_is_subtype if sub_klass is a -// subtype of super_klass. -// -// Args: -// rax: superklass -// Rsub_klass: subklass -// -// Kills: -// rcx, rdi -void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, - Label& ok_is_subtype) { - assert(Rsub_klass != rax, "rax holds superklass"); - assert(Rsub_klass != r14, "r14 holds locals"); - assert(Rsub_klass != r13, "r13 holds bcp"); - assert(Rsub_klass != rcx, "rcx holds 2ndary super array length"); - assert(Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr"); - - // Profile the not-null value's klass. - profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, reloads rdi - - // Do the check. - check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx - - // Profile the failure of the check. - profile_typecheck_failed(rcx); // blows rcx -} - - - -// Java Expression Stack - -void InterpreterMacroAssembler::pop_ptr(Register r) { - pop(r); -} - -void InterpreterMacroAssembler::pop_i(Register r) { - // XXX can't use pop currently, upper half non clean - movl(r, Address(rsp, 0)); - addptr(rsp, wordSize); -} - -void InterpreterMacroAssembler::pop_l(Register r) { - movq(r, Address(rsp, 0)); - addptr(rsp, 2 * Interpreter::stackElementSize); -} - -void InterpreterMacroAssembler::pop_f(XMMRegister r) { - movflt(r, Address(rsp, 0)); - addptr(rsp, wordSize); -} - -void InterpreterMacroAssembler::pop_d(XMMRegister r) { - movdbl(r, Address(rsp, 0)); - addptr(rsp, 2 * Interpreter::stackElementSize); -} - -void InterpreterMacroAssembler::push_ptr(Register r) { - push(r); -} - -void InterpreterMacroAssembler::push_i(Register r) { - push(r); -} - -void InterpreterMacroAssembler::push_l(Register r) { - subptr(rsp, 2 * wordSize); - movq(Address(rsp, 0), r); -} - -void InterpreterMacroAssembler::push_f(XMMRegister r) { - subptr(rsp, wordSize); - movflt(Address(rsp, 0), r); -} - -void InterpreterMacroAssembler::push_d(XMMRegister r) { - subptr(rsp, 2 * wordSize); - movdbl(Address(rsp, 0), r); -} - -void InterpreterMacroAssembler::pop(TosState state) { - switch (state) { - case atos: pop_ptr(); break; - case btos: - case ctos: - case stos: - case itos: pop_i(); break; - case ltos: pop_l(); break; - case ftos: pop_f(); break; - case dtos: pop_d(); break; - case vtos: /* nothing to do */ break; - default: ShouldNotReachHere(); - } - verify_oop(rax, state); -} - -void InterpreterMacroAssembler::push(TosState state) { - verify_oop(rax, state); - switch (state) { - case atos: push_ptr(); break; - case btos: - case ctos: - case stos: - case itos: push_i(); break; - case ltos: push_l(); break; - case ftos: push_f(); break; - case dtos: push_d(); break; - case vtos: /* nothing to do */ break; - default : ShouldNotReachHere(); - } -} - - -// Helpers for swap and dup -void InterpreterMacroAssembler::load_ptr(int n, Register val) { - movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); -} - -void InterpreterMacroAssembler::store_ptr(int n, Register val) { - movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); -} - - -void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { - // set sender sp - lea(r13, Address(rsp, wordSize)); - // record last_sp - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13); -} - - -// Jump to from_interpreted entry of a call unless single stepping is possible -// in this thread in which case we must call the i2i entry -void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { - prepare_to_jump_from_interpreted(); - - if (JvmtiExport::can_post_interpreter_events()) { - Label run_compiled_code; - // JVMTI events, such as single-stepping, are implemented partly by avoiding running - // compiled code in threads for which the event is enabled. Check here for - // interp_only_mode if these events CAN be enabled. - // interp_only is an int, on little endian it is sufficient to test the byte only - // Is a cmpl faster? - cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0); - jccb(Assembler::zero, run_compiled_code); - jmp(Address(method, Method::interpreter_entry_offset())); - bind(run_compiled_code); - } - - jmp(Address(method, Method::from_interpreted_offset())); - -} - - -// The following two routines provide a hook so that an implementation -// can schedule the dispatch in two parts. amd64 does not do this. -void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { - // Nothing amd64 specific to be done here -} - -void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { - dispatch_next(state, step); -} - -void InterpreterMacroAssembler::dispatch_base(TosState state, - address* table, - bool verifyoop) { - verify_FPU(1, state); - if (VerifyActivationFrameSize) { - Label L; - mov(rcx, rbp); - subptr(rcx, rsp); - int32_t min_frame_size = - (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * - wordSize; - cmpptr(rcx, (int32_t)min_frame_size); - jcc(Assembler::greaterEqual, L); - stop("broken stack frame"); - bind(L); - } - if (verifyoop) { - verify_oop(rax, state); - } - lea(rscratch1, ExternalAddress((address)table)); - jmp(Address(rscratch1, rbx, Address::times_8)); -} - -void InterpreterMacroAssembler::dispatch_only(TosState state) { - dispatch_base(state, Interpreter::dispatch_table(state)); -} - -void InterpreterMacroAssembler::dispatch_only_normal(TosState state) { - dispatch_base(state, Interpreter::normal_table(state)); -} - -void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) { - dispatch_base(state, Interpreter::normal_table(state), false); -} - - -void InterpreterMacroAssembler::dispatch_next(TosState state, int step) { - // load next bytecode (load before advancing r13 to prevent AGI) - load_unsigned_byte(rbx, Address(r13, step)); - // advance r13 - increment(r13, step); - dispatch_base(state, Interpreter::dispatch_table(state)); -} - -void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { - // load current bytecode - load_unsigned_byte(rbx, Address(r13, 0)); - dispatch_base(state, table); -} - -// remove activation -// -// Unlock the receiver if this is a synchronized method. -// Unlock any Java monitors from syncronized blocks. -// Remove the activation from the stack. -// -// If there are locked Java monitors -// If throw_monitor_exception -// throws IllegalMonitorStateException -// Else if install_monitor_exception -// installs IllegalMonitorStateException -// Else -// no error processing -void InterpreterMacroAssembler::remove_activation( - TosState state, - Register ret_addr, - bool throw_monitor_exception, - bool install_monitor_exception, - bool notify_jvmdi) { - // Note: Registers rdx xmm0 may be in use for the - // result check if synchronized method - Label unlocked, unlock, no_unlock; - - // get the value of _do_not_unlock_if_synchronized into rdx - const Address do_not_unlock_if_synchronized(r15_thread, - in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); - movbool(rdx, do_not_unlock_if_synchronized); - movbool(do_not_unlock_if_synchronized, false); // reset the flag - - // get method access flags - movptr(rbx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); - movl(rcx, Address(rbx, Method::access_flags_offset())); - testl(rcx, JVM_ACC_SYNCHRONIZED); - jcc(Assembler::zero, unlocked); - - // Don't unlock anything if the _do_not_unlock_if_synchronized flag - // is set. - testbool(rdx); - jcc(Assembler::notZero, no_unlock); - - // unlock monitor - push(state); // save result - - // BasicObjectLock will be first in list, since this is a - // synchronized method. However, need to check that the object has - // not been unlocked by an explicit monitorexit bytecode. - const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * - wordSize - (int) sizeof(BasicObjectLock)); - // We use c_rarg1 so that if we go slow path it will be the correct - // register for unlock_object to pass to VM directly - lea(c_rarg1, monitor); // address of first monitor - - movptr(rax, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); - testptr(rax, rax); - jcc(Assembler::notZero, unlock); - - pop(state); - if (throw_monitor_exception) { - // Entry already unlocked, need to throw exception - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_illegal_monitor_state_exception)); - should_not_reach_here(); - } else { - // Monitor already unlocked during a stack unroll. If requested, - // install an illegal_monitor_state_exception. Continue with - // stack unrolling. - if (install_monitor_exception) { - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::new_illegal_monitor_state_exception)); - } - jmp(unlocked); - } - - bind(unlock); - unlock_object(c_rarg1); - pop(state); - - // Check that for block-structured locking (i.e., that all locked - // objects has been unlocked) - bind(unlocked); - - // rax: Might contain return value - - // Check that all monitors are unlocked - { - Label loop, exception, entry, restart; - const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; - 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); - - bind(restart); - // We use c_rarg1 so that if we go slow path it will be the correct - // register for unlock_object to pass to VM directly - movptr(c_rarg1, 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 - jmp(entry); - - // Entry already locked, need to throw exception - bind(exception); - - if (throw_monitor_exception) { - // Throw exception - MacroAssembler::call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime:: - throw_illegal_monitor_state_exception)); - should_not_reach_here(); - } else { - // Stack unrolling. Unlock object and install illegal_monitor_exception. - // Unlock does not block, so don't have to worry about the frame. - // We don't have to preserve c_rarg1 since we are going to throw an exception. - - push(state); - unlock_object(c_rarg1); - pop(state); - - if (install_monitor_exception) { - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime:: - new_illegal_monitor_state_exception)); - } - - jmp(restart); - } - - bind(loop); - // check if current entry is used - cmpptr(Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL); - jcc(Assembler::notEqual, exception); - - addptr(c_rarg1, entry_size); // otherwise advance to next entry - bind(entry); - cmpptr(c_rarg1, rbx); // check if bottom reached - jcc(Assembler::notEqual, loop); // if not at bottom then check this entry - } - - bind(no_unlock); - - // jvmti support - if (notify_jvmdi) { - notify_method_exit(state, NotifyJVMTI); // preserve TOSCA - } else { - notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA - } - - // remove activation - // get sender sp - movptr(rbx, - Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); - leave(); // remove frame anchor - pop(ret_addr); // get return address - mov(rsp, rbx); // set sp to sender sp -} - -#endif // C_INTERP - -void InterpreterMacroAssembler::get_method_counters(Register method, - Register mcs, Label& skip) { - Label has_counters; - movptr(mcs, Address(method, Method::method_counters_offset())); - testptr(mcs, mcs); - jcc(Assembler::notZero, has_counters); - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::build_method_counters), method); - movptr(mcs, Address(method,Method::method_counters_offset())); - testptr(mcs, mcs); - jcc(Assembler::zero, skip); // No MethodCounters allocated, OutOfMemory - bind(has_counters); -} - - -// Lock object -// -// Args: -// c_rarg1: BasicObjectLock to be used for locking -// -// Kills: -// rax -// c_rarg0, c_rarg1, c_rarg2, c_rarg3, .. (param regs) -// rscratch1, rscratch2 (scratch regs) -void InterpreterMacroAssembler::lock_object(Register lock_reg) { - assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1"); - - if (UseHeavyMonitors) { - call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), - lock_reg); - } else { - Label done; - - const Register swap_reg = rax; // Must use rax for cmpxchg instruction - const Register obj_reg = c_rarg3; // Will contain the oop - - const int obj_offset = BasicObjectLock::obj_offset_in_bytes(); - const int lock_offset = BasicObjectLock::lock_offset_in_bytes (); - const int mark_offset = lock_offset + - BasicLock::displaced_header_offset_in_bytes(); - - Label slow_case; - - // Load object pointer into obj_reg %c_rarg3 - movptr(obj_reg, Address(lock_reg, obj_offset)); - - if (UseBiasedLocking) { - biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, done, &slow_case); - } - - // Load immediate 1 into swap_reg %rax - movl(swap_reg, 1); - - // Load (object->mark() | 1) into swap_reg %rax - orptr(swap_reg, Address(obj_reg, 0)); - - // Save (object->mark() | 1) into BasicLock's displaced header - movptr(Address(lock_reg, mark_offset), swap_reg); - - assert(lock_offset == 0, - "displached header must be first word in BasicObjectLock"); - - if (os::is_MP()) lock(); - cmpxchgptr(lock_reg, Address(obj_reg, 0)); - if (PrintBiasedLockingStatistics) { - cond_inc32(Assembler::zero, - ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); - } - jcc(Assembler::zero, done); - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 7) == 0, and - // 2) rsp <= mark < mark + os::pagesize() - // - // These 3 tests can be done by evaluating the following - // expression: ((mark - rsp) & (7 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 3 bits clear. - // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg - subptr(swap_reg, rsp); - andptr(swap_reg, 7 - os::vm_page_size()); - - // Save the test result, for recursive case, the result is zero - movptr(Address(lock_reg, mark_offset), swap_reg); - - if (PrintBiasedLockingStatistics) { - cond_inc32(Assembler::zero, - ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); - } - jcc(Assembler::zero, done); - - bind(slow_case); - - // Call the runtime routine for slow case - call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), - lock_reg); - - bind(done); - } -} - - -// Unlocks an object. Used in monitorexit bytecode and -// remove_activation. Throws an IllegalMonitorException if object is -// not locked by current thread. -// -// Args: -// c_rarg1: BasicObjectLock for lock -// -// Kills: -// rax -// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ... (param regs) -// rscratch1, rscratch2 (scratch regs) -void InterpreterMacroAssembler::unlock_object(Register lock_reg) { - assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1"); - - if (UseHeavyMonitors) { - call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), - lock_reg); - } else { - Label done; - - const Register swap_reg = rax; // Must use rax for cmpxchg instruction - const Register header_reg = c_rarg2; // Will contain the old oopMark - const Register obj_reg = c_rarg3; // Will contain the oop - - save_bcp(); // Save in case of exception - - // Convert from BasicObjectLock structure to object and BasicLock - // structure Store the BasicLock address into %rax - lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); - - // Load oop into obj_reg(%c_rarg3) - movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); - - // Free entry - movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); - - if (UseBiasedLocking) { - biased_locking_exit(obj_reg, header_reg, done); - } - - // Load the old header from BasicLock structure - movptr(header_reg, Address(swap_reg, - BasicLock::displaced_header_offset_in_bytes())); - - // Test for recursion - testptr(header_reg, header_reg); - - // zero for recursive case - jcc(Assembler::zero, done); - - // Atomic swap back the old header - if (os::is_MP()) lock(); - cmpxchgptr(header_reg, Address(obj_reg, 0)); - - // zero for recursive case - jcc(Assembler::zero, done); - - // Call the runtime routine for slow case. - movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), - obj_reg); // restore obj - call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), - lock_reg); - - bind(done); - - restore_bcp(); - } -} - -#ifndef CC_INTERP - -void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, - Label& zero_continue) { - assert(ProfileInterpreter, "must be profiling interpreter"); - movptr(mdp, Address(rbp, frame::interpreter_frame_mdp_offset * wordSize)); - testptr(mdp, mdp); - jcc(Assembler::zero, zero_continue); -} - - -// Set the method data pointer for the current bcp. -void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { - assert(ProfileInterpreter, "must be profiling interpreter"); - Label set_mdp; - push(rax); - push(rbx); - - get_method(rbx); - // Test MDO to avoid the call if it is NULL. - movptr(rax, Address(rbx, in_bytes(Method::method_data_offset()))); - testptr(rax, rax); - jcc(Assembler::zero, set_mdp); - // rbx: method - // r13: bcp - call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, r13); - // rax: mdi - // mdo is guaranteed to be non-zero here, we checked for it before the call. - movptr(rbx, Address(rbx, in_bytes(Method::method_data_offset()))); - addptr(rbx, in_bytes(MethodData::data_offset())); - addptr(rax, rbx); - bind(set_mdp); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), rax); - pop(rbx); - pop(rax); -} - -void InterpreterMacroAssembler::verify_method_data_pointer() { - assert(ProfileInterpreter, "must be profiling interpreter"); -#ifdef ASSERT - Label verify_continue; - push(rax); - push(rbx); - push(c_rarg3); - push(c_rarg2); - test_method_data_pointer(c_rarg3, verify_continue); // If mdp is zero, continue - get_method(rbx); - - // If the mdp is valid, it will point to a DataLayout header which is - // consistent with the bcp. The converse is highly probable also. - load_unsigned_short(c_rarg2, - Address(c_rarg3, in_bytes(DataLayout::bci_offset()))); - addptr(c_rarg2, Address(rbx, Method::const_offset())); - lea(c_rarg2, Address(c_rarg2, ConstMethod::codes_offset())); - cmpptr(c_rarg2, r13); - jcc(Assembler::equal, verify_continue); - // rbx: method - // r13: bcp - // c_rarg3: mdp - call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), - rbx, r13, c_rarg3); - bind(verify_continue); - pop(c_rarg2); - pop(c_rarg3); - pop(rbx); - pop(rax); -#endif // ASSERT -} - - -void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, - int constant, - Register value) { - assert(ProfileInterpreter, "must be profiling interpreter"); - Address data(mdp_in, constant); - movptr(data, value); -} - - -void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, - int constant, - bool decrement) { - // Counter address - Address data(mdp_in, constant); - - increment_mdp_data_at(data, decrement); -} - -void InterpreterMacroAssembler::increment_mdp_data_at(Address data, - bool decrement) { - assert(ProfileInterpreter, "must be profiling interpreter"); - // %%% this does 64bit counters at best it is wasting space - // at worst it is a rare bug when counters overflow - - if (decrement) { - // Decrement the register. Set condition codes. - addptr(data, (int32_t) -DataLayout::counter_increment); - // If the decrement causes the counter to overflow, stay negative - Label L; - jcc(Assembler::negative, L); - addptr(data, (int32_t) DataLayout::counter_increment); - bind(L); - } else { - assert(DataLayout::counter_increment == 1, - "flow-free idiom only works with 1"); - // Increment the register. Set carry flag. - addptr(data, DataLayout::counter_increment); - // If the increment causes the counter to overflow, pull back by 1. - sbbptr(data, (int32_t)0); - } -} - - -void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, - Register reg, - int constant, - bool decrement) { - Address data(mdp_in, reg, Address::times_1, constant); - - increment_mdp_data_at(data, decrement); -} - -void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, - int flag_byte_constant) { - assert(ProfileInterpreter, "must be profiling interpreter"); - int header_offset = in_bytes(DataLayout::header_offset()); - int header_bits = DataLayout::flag_mask_to_header_mask(flag_byte_constant); - // Set the flag - orl(Address(mdp_in, header_offset), header_bits); -} - - - -void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, - int offset, - Register value, - Register test_value_out, - Label& not_equal_continue) { - assert(ProfileInterpreter, "must be profiling interpreter"); - if (test_value_out == noreg) { - cmpptr(value, Address(mdp_in, offset)); - } else { - // Put the test value into a register, so caller can use it: - movptr(test_value_out, Address(mdp_in, offset)); - cmpptr(test_value_out, value); - } - jcc(Assembler::notEqual, not_equal_continue); -} - - -void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, - int offset_of_disp) { - assert(ProfileInterpreter, "must be profiling interpreter"); - Address disp_address(mdp_in, offset_of_disp); - addptr(mdp_in, disp_address); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); -} - - -void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, - Register reg, - int offset_of_disp) { - assert(ProfileInterpreter, "must be profiling interpreter"); - Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); - addptr(mdp_in, disp_address); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); -} - - -void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, - int constant) { - assert(ProfileInterpreter, "must be profiling interpreter"); - addptr(mdp_in, constant); - movptr(Address(rbp, frame::interpreter_frame_mdp_offset * wordSize), mdp_in); -} - - -void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { - assert(ProfileInterpreter, "must be profiling interpreter"); - push(return_bci); // save/restore across call_VM - call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), - return_bci); - pop(return_bci); -} - - -void InterpreterMacroAssembler::profile_taken_branch(Register mdp, - Register bumped_count) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - // Otherwise, assign to mdp - test_method_data_pointer(mdp, profile_continue); - - // We are taking a branch. Increment the taken count. - // We inline increment_mdp_data_at to return bumped_count in a register - //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); - Address data(mdp, in_bytes(JumpData::taken_offset())); - movptr(bumped_count, data); - assert(DataLayout::counter_increment == 1, - "flow-free idiom only works with 1"); - addptr(bumped_count, DataLayout::counter_increment); - sbbptr(bumped_count, 0); - movptr(data, bumped_count); // Store back out - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // We are taking a branch. Increment the not taken count. - increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); - - // The method data pointer needs to be updated to correspond to - // the next bytecode - update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); - bind(profile_continue); - } -} - -void InterpreterMacroAssembler::profile_call(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // We are making a call. Increment the count. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_final_call(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // We are making a call. Increment the count. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, - in_bytes(VirtualCallData:: - virtual_call_data_size())); - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_virtual_call(Register receiver, - Register mdp, - Register reg2, - bool receiver_can_be_null) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - Label skip_receiver_profile; - if (receiver_can_be_null) { - Label not_null; - testptr(receiver, receiver); - jccb(Assembler::notZero, not_null); - // We are making a call. Increment the count for null receiver. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - jmp(skip_receiver_profile); - bind(not_null); - } - - // Record the receiver type. - record_klass_in_profile(receiver, mdp, reg2, true); - bind(skip_receiver_profile); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, - in_bytes(VirtualCallData:: - virtual_call_data_size())); - bind(profile_continue); - } -} - -// This routine creates a state machine for updating the multi-row -// type profile at a virtual call site (or other type-sensitive bytecode). -// The machine visits each row (of receiver/count) until the receiver type -// is found, or until it runs out of rows. At the same time, it remembers -// the location of the first empty row. (An empty row records null for its -// receiver, and can be allocated for a newly-observed receiver type.) -// Because there are two degrees of freedom in the state, a simple linear -// search will not work; it must be a decision tree. Hence this helper -// function is recursive, to generate the required tree structured code. -// It's the interpreter, so we are trading off code space for speed. -// See below for example code. -void InterpreterMacroAssembler::record_klass_in_profile_helper( - Register receiver, Register mdp, - Register reg2, int start_row, - Label& done, bool is_virtual_call) { - if (TypeProfileWidth == 0) { - if (is_virtual_call) { - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - } - return; - } - - int last_row = VirtualCallData::row_limit() - 1; - assert(start_row <= last_row, "must be work left to do"); - // Test this row for both the receiver and for null. - // Take any of three different outcomes: - // 1. found receiver => increment count and goto done - // 2. found null => keep looking for case 1, maybe allocate this cell - // 3. found something else => keep looking for cases 1 and 2 - // Case 3 is handled by a recursive call. - for (int row = start_row; row <= last_row; row++) { - Label next_test; - bool test_for_null_also = (row == start_row); - - // See if the receiver is receiver[n]. - int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); - test_mdp_data_at(mdp, recvr_offset, receiver, - (test_for_null_also ? reg2 : noreg), - next_test); - // (Reg2 now contains the receiver from the CallData.) - - // The receiver is receiver[n]. Increment count[n]. - int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); - increment_mdp_data_at(mdp, count_offset); - jmp(done); - bind(next_test); - - if (test_for_null_also) { - Label found_null; - // Failed the equality check on receiver[n]... Test for null. - testptr(reg2, reg2); - if (start_row == last_row) { - // The only thing left to do is handle the null case. - if (is_virtual_call) { - jccb(Assembler::zero, found_null); - // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polymorphic case. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - jmp(done); - bind(found_null); - } else { - jcc(Assembler::notZero, done); - } - break; - } - // Since null is rare, make it be the branch-taken case. - jcc(Assembler::zero, found_null); - - // Put all the "Case 3" tests here. - record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); - - // Found a null. Keep searching for a matching receiver, - // but remember that this is an empty (unused) slot. - bind(found_null); - } - } - - // In the fall-through case, we found no matching receiver, but we - // observed the receiver[start_row] is NULL. - - // Fill in the receiver field and increment the count. - int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); - set_mdp_data_at(mdp, recvr_offset, receiver); - int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); - movl(reg2, DataLayout::counter_increment); - set_mdp_data_at(mdp, count_offset, reg2); - if (start_row > 0) { - jmp(done); - } -} - -// Example state machine code for three profile rows: -// // main copy of decision tree, rooted at row[1] -// if (row[0].rec == rec) { row[0].incr(); goto done; } -// if (row[0].rec != NULL) { -// // inner copy of decision tree, rooted at row[1] -// if (row[1].rec == rec) { row[1].incr(); goto done; } -// if (row[1].rec != NULL) { -// // degenerate decision tree, rooted at row[2] -// if (row[2].rec == rec) { row[2].incr(); goto done; } -// if (row[2].rec != NULL) { count.incr(); goto done; } // overflow -// row[2].init(rec); goto done; -// } else { -// // remember row[1] is empty -// if (row[2].rec == rec) { row[2].incr(); goto done; } -// row[1].init(rec); goto done; -// } -// } else { -// // remember row[0] is empty -// if (row[1].rec == rec) { row[1].incr(); goto done; } -// if (row[2].rec == rec) { row[2].incr(); goto done; } -// row[0].init(rec); goto done; -// } -// done: - -void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, - Register mdp, Register reg2, - bool is_virtual_call) { - assert(ProfileInterpreter, "must be profiling"); - Label done; - - record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); - - bind (done); -} - -void InterpreterMacroAssembler::profile_ret(Register return_bci, - Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - uint row; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // Update the total ret count. - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); - - for (row = 0; row < RetData::row_limit(); row++) { - Label next_test; - - // See if return_bci is equal to bci[n]: - test_mdp_data_at(mdp, - in_bytes(RetData::bci_offset(row)), - return_bci, noreg, - next_test); - - // return_bci is equal to bci[n]. Increment the count. - increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); - - // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_offset(mdp, - in_bytes(RetData::bci_displacement_offset(row))); - jmp(profile_continue); - bind(next_test); - } - - update_mdp_for_ret(return_bci); - - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_null_seen(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); - - // The method data pointer needs to be updated. - int mdp_delta = in_bytes(BitData::bit_data_size()); - if (TypeProfileCasts) { - mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); - } - update_mdp_by_constant(mdp, mdp_delta); - - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { - if (ProfileInterpreter && TypeProfileCasts) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - int count_offset = in_bytes(CounterData::count_offset()); - // Back up the address, since we have already bumped the mdp. - count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); - - // *Decrement* the counter. We expect to see zero or small negatives. - increment_mdp_data_at(mdp, count_offset, true); - - bind (profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // The method data pointer needs to be updated. - int mdp_delta = in_bytes(BitData::bit_data_size()); - if (TypeProfileCasts) { - mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); - - // Record the object type. - record_klass_in_profile(klass, mdp, reg2, false); - } - update_mdp_by_constant(mdp, mdp_delta); - - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_switch_default(Register mdp) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // Update the default case count - increment_mdp_data_at(mdp, - in_bytes(MultiBranchData::default_count_offset())); - - // The method data pointer needs to be updated. - update_mdp_by_offset(mdp, - in_bytes(MultiBranchData:: - default_displacement_offset())); - - bind(profile_continue); - } -} - - -void InterpreterMacroAssembler::profile_switch_case(Register index, - Register mdp, - Register reg2) { - if (ProfileInterpreter) { - Label profile_continue; - - // If no method data exists, go to profile_continue. - test_method_data_pointer(mdp, profile_continue); - - // Build the base (index * per_case_size_in_bytes()) + - // case_array_offset_in_bytes() - movl(reg2, in_bytes(MultiBranchData::per_case_size())); - imulptr(index, reg2); // XXX l ? - addptr(index, in_bytes(MultiBranchData::case_array_offset())); // XXX l ? - - // Update the case count - increment_mdp_data_at(mdp, - index, - in_bytes(MultiBranchData::relative_count_offset())); - - // The method data pointer needs to be updated. - update_mdp_by_offset(mdp, - index, - in_bytes(MultiBranchData:: - relative_displacement_offset())); - - bind(profile_continue); - } -} - - - -void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { - if (state == atos) { - MacroAssembler::verify_oop(reg); - } -} - -void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { -} - -// Jump if ((*counter_addr += increment) & mask) satisfies the condition. -void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, - int increment, Address mask, - Register scratch, bool preloaded, - Condition cond, Label* where) { - if (!preloaded) { - movl(scratch, counter_addr); - } - incrementl(scratch, increment); - movl(counter_addr, scratch); - andl(scratch, mask); - jcc(cond, *where); -} -#endif // !CC_INTERP - - -void InterpreterMacroAssembler::notify_method_entry() { - // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to - // track stack depth. If it is possible to enter interp_only_mode we add - // the code to check if the event should be sent. - if (JvmtiExport::can_post_interpreter_events()) { - Label L; - movl(rdx, Address(r15_thread, JavaThread::interp_only_mode_offset())); - testl(rdx, rdx); - jcc(Assembler::zero, L); - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::post_method_entry)); - bind(L); - } - - { - SkipIfEqual skip(this, &DTraceMethodProbes, false); - get_method(c_rarg1); - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), - r15_thread, c_rarg1); - } - - // RedefineClasses() tracing support for obsolete method entry - if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { - get_method(c_rarg1); - call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), - r15_thread, c_rarg1); - } -} - - -void InterpreterMacroAssembler::notify_method_exit( - TosState state, NotifyMethodExitMode mode) { - // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to - // track stack depth. If it is possible to enter interp_only_mode we add - // the code to check if the event should be sent. - if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { - Label L; - // Note: frame::interpreter_frame_result has a dependency on how the - // method result is saved across the call to post_method_exit. If this - // is changed then the interpreter_frame_result implementation will - // need to be updated too. - - // For c++ interpreter the result is always stored at a known location in the frame - // template interpreter will leave it on the top of the stack. - NOT_CC_INTERP(push(state);) - movl(rdx, Address(r15_thread, JavaThread::interp_only_mode_offset())); - testl(rdx, rdx); - jcc(Assembler::zero, L); - call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); - bind(L); - NOT_CC_INTERP(pop(state)); - } - - { - SkipIfEqual skip(this, &DTraceMethodProbes, false); - NOT_CC_INTERP(push(state)); - get_method(c_rarg1); - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), - r15_thread, c_rarg1); - NOT_CC_INTERP(pop(state)); - } -} - diff -r d47c58140b41 -r 427f83353f73 hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Tue Mar 31 16:22:59 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,240 +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. - * - */ - -#ifndef CC_INTERP - protected: - // Interpreter specific version of call_VM_base - virtual void call_VM_leaf_base(address entry_point, - int number_of_arguments); - - virtual void call_VM_base(Register oop_result, - Register java_thread, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions); - - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - - // base routine for all dispatches - void dispatch_base(TosState state, address* table, bool verifyoop = true); -#endif // CC_INTERP - - public: - InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(r14), _bcp_register(r13) {} - - void load_earlyret_value(TosState state); - -#ifdef CC_INTERP - void save_bcp() { /* not needed in c++ interpreter and harmless */ } - void restore_bcp() { /* not needed in c++ interpreter and harmless */ } - - // Helpers for runtime call arguments/results - void get_method(Register reg); - -#else - - // Interpreter-specific registers - void save_bcp() { - movptr(Address(rbp, frame::interpreter_frame_bcp_offset * wordSize), r13); - } - - void restore_bcp() { - movptr(r13, Address(rbp, frame::interpreter_frame_bcp_offset * wordSize)); - } - - void restore_locals() { - movptr(r14, Address(rbp, frame::interpreter_frame_locals_offset * wordSize)); - } - - // Helpers for runtime call arguments/results - void get_method(Register reg) { - movptr(reg, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); - } - - void get_const(Register reg) { - get_method(reg); - movptr(reg, Address(reg, Method::const_offset())); - } - - void get_constant_pool(Register reg) { - get_const(reg); - movptr(reg, Address(reg, ConstMethod::constants_offset())); - } - - void get_constant_pool_cache(Register reg) { - get_constant_pool(reg); - movptr(reg, Address(reg, ConstantPool::cache_offset_in_bytes())); - } - - void get_cpool_and_tags(Register cpool, Register tags) { - get_constant_pool(cpool); - movptr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes())); - } - - void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); - void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); - void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); - void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); - void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); - - // load cpool->resolved_references(index); - void load_resolved_reference_at_index(Register result, Register index); - - void pop_ptr(Register r = rax); - void pop_i(Register r = rax); - void pop_l(Register r = rax); - void pop_f(XMMRegister r = xmm0); - void pop_d(XMMRegister r = xmm0); - void push_ptr(Register r = rax); - void push_i(Register r = rax); - void push_l(Register r = rax); - void push_f(XMMRegister r = xmm0); - void push_d(XMMRegister r = xmm0); - - void pop(Register r ) { ((MacroAssembler*)this)->pop(r); } - - void push(Register r ) { ((MacroAssembler*)this)->push(r); } - void push(int32_t imm ) { ((MacroAssembler*)this)->push(imm); } - - void pop(TosState state); // transition vtos -> state - void push(TosState state); // transition state -> vtos - - void empty_expression_stack() { - movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); - // NULL last_sp until next java call - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - } - - // Helpers for swap and dup - void load_ptr(int n, Register val); - void store_ptr(int n, Register val); - - // Generate a subtype check: branch to ok_is_subtype if sub_klass is - // a subtype of super_klass. - void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); - - // Dispatching - void dispatch_prolog(TosState state, int step = 0); - void dispatch_epilog(TosState state, int step = 0); - // dispatch via ebx (assume ebx is loaded already) - void dispatch_only(TosState state); - // dispatch normal table via ebx (assume ebx is loaded already) - void dispatch_only_normal(TosState state); - void dispatch_only_noverify(TosState state); - // load ebx from [esi + step] and dispatch via ebx - void dispatch_next(TosState state, int step = 0); - // load ebx from [esi] and dispatch via ebx and table - void dispatch_via (TosState state, address* table); - - // jump to an invoked target - void prepare_to_jump_from_interpreted(); - void jump_from_interpreted(Register method, Register temp); - - - // Returning from interpreted functions - // - // Removes the current activation (incl. unlocking of monitors) - // and sets up the return address. This code is also used for - // exception unwindwing. In that case, we do not want to throw - // IllegalMonitorStateExceptions, since that might get us into an - // infinite rethrow exception loop. - // Additionally this code is used for popFrame and earlyReturn. - // In popFrame case we want to skip throwing an exception, - // installing an exception, and notifying jvmdi. - // In earlyReturn case we only want to skip throwing an exception - // and installing an exception. - void remove_activation(TosState state, Register ret_addr, - bool throw_monitor_exception = true, - bool install_monitor_exception = true, - bool notify_jvmdi = true); -#endif // CC_INTERP - void get_method_counters(Register method, Register mcs, Label& skip); - - // Object locking - void lock_object (Register lock_reg); - void unlock_object(Register lock_reg); - -#ifndef CC_INTERP - - // Interpreter profiling operations - void set_method_data_pointer_for_bcp(); - void test_method_data_pointer(Register mdp, Label& zero_continue); - void verify_method_data_pointer(); - - void set_mdp_data_at(Register mdp_in, int constant, Register value); - void increment_mdp_data_at(Address data, bool decrement = false); - void increment_mdp_data_at(Register mdp_in, int constant, - bool decrement = false); - void increment_mdp_data_at(Register mdp_in, Register reg, int constant, - bool decrement = false); - void increment_mask_and_jump(Address counter_addr, - int increment, Address mask, - Register scratch, bool preloaded, - Condition cond, Label* where); - void set_mdp_flag_at(Register mdp_in, int flag_constant); - void test_mdp_data_at(Register mdp_in, int offset, Register value, - Register test_value_out, - Label& not_equal_continue); - - void record_klass_in_profile(Register receiver, Register mdp, - Register reg2, bool is_virtual_call); - void record_klass_in_profile_helper(Register receiver, Register mdp, - Register reg2, int start_row, - Label& done, bool is_virtual_call); - - void update_mdp_by_offset(Register mdp_in, int offset_of_offset); - void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); - void update_mdp_by_constant(Register mdp_in, int constant); - void update_mdp_for_ret(Register return_bci); - - void profile_taken_branch(Register mdp, Register bumped_count); - void profile_not_taken_branch(Register mdp); - void profile_call(Register mdp); - void profile_final_call(Register mdp); - void profile_virtual_call(Register receiver, Register mdp, - Register scratch2, - bool receiver_can_be_null = false); - void profile_ret(Register return_bci, Register mdp); - void profile_null_seen(Register mdp); - void profile_typecheck(Register mdp, Register klass, Register scratch); - void profile_typecheck_failed(Register mdp); - void profile_switch_default(Register mdp); - void profile_switch_case(Register index_in_scratch, Register mdp, - Register scratch2); - - // Debugging - // only if +VerifyOops && state == atos - void verify_oop(Register reg, TosState state = atos); - // only if +VerifyFPU && (state == ftos || state == dtos) - void verify_FPU(int stack_depth, TosState state = ftos); - -#endif // !CC_INTERP - - typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; - - // support for jvmti/dtrace - void notify_method_entry(); - void notify_method_exit(TosState state, NotifyMethodExitMode mode); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/aix/vm/vmError_aix.cpp --- a/hotspot/src/os/aix/vm/vmError_aix.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/aix/vm/vmError_aix.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -109,7 +109,15 @@ } sigthreadmask(SIG_UNBLOCK, &newset, NULL); - VMError err(NULL, sig, NULL, info, ucVoid); + // support safefetch faults in error handling + ucontext_t* const uc = (ucontext_t*) ucVoid; + address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL; + if (uc && pc && StubRoutines::is_safefetch_fault(pc)) { + os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); + return; + } + + VMError err(NULL, sig, pc, info, ucVoid); err.report_and_die(); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/bsd/vm/os_bsd.hpp --- a/hotspot/src/os/bsd/vm/os_bsd.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -99,6 +99,7 @@ static void set_page_size(int val) { _page_size = val; } static address ucontext_get_pc(ucontext_t* uc); + static void ucontext_set_pc(ucontext_t* uc, address pc); static intptr_t* ucontext_get_sp(ucontext_t* uc); static intptr_t* ucontext_get_fp(ucontext_t* uc); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/bsd/vm/vmError_bsd.cpp --- a/hotspot/src/os/bsd/vm/vmError_bsd.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/bsd/vm/vmError_bsd.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -112,7 +112,16 @@ } pthread_sigmask(SIG_UNBLOCK, &newset, NULL); - VMError err(NULL, sig, NULL, info, ucVoid); + // support safefetch faults in error handling + ucontext_t* const uc = (ucontext_t*) ucVoid; + address const pc = uc ? os::Bsd::ucontext_get_pc(uc) : NULL; + + if (uc && pc && StubRoutines::is_safefetch_fault(pc)) { + os::Bsd::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); + return; + } + + VMError err(NULL, sig, pc, info, ucVoid); err.report_and_die(); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -3732,14 +3732,14 @@ // Does this overlap the block we wanted? Give back the overlapped // parts and try again. - size_t top_overlap = requested_addr + (bytes + gap) - base[i]; - if (top_overlap >= 0 && top_overlap < bytes) { + ptrdiff_t top_overlap = requested_addr + (bytes + gap) - base[i]; + if (top_overlap >= 0 && (size_t)top_overlap < bytes) { unmap_memory(base[i], top_overlap); base[i] += top_overlap; size[i] = bytes - top_overlap; } else { - size_t bottom_overlap = base[i] + bytes - requested_addr; - if (bottom_overlap >= 0 && bottom_overlap < bytes) { + ptrdiff_t bottom_overlap = base[i] + bytes - requested_addr; + if (bottom_overlap >= 0 && (size_t)bottom_overlap < bytes) { unmap_memory(requested_addr, bottom_overlap); size[i] = bytes - bottom_overlap; } else { @@ -6003,11 +6003,11 @@ } if (strlen(core_pattern) == 0) { - return 0; + return -1; } char *pid_pos = strstr(core_pattern, "%p"); - size_t written; + int written; if (core_pattern[0] == '/') { written = jio_snprintf(buffer, bufferSize, core_pattern); @@ -6016,8 +6016,7 @@ const char* p = get_current_directory(cwd, PATH_MAX); if (p == NULL) { - assert(p != NULL, "failed to get current directory"); - return 0; + return -1; } if (core_pattern[0] == '|') { @@ -6029,8 +6028,11 @@ } } - if ((written >= 0) && (written < bufferSize) - && (pid_pos == NULL) && (core_pattern[0] != '|')) { + if (written < 0) { + return -1; + } + + if (((size_t)written < bufferSize) && (pid_pos == NULL) && (core_pattern[0] != '|')) { int core_uses_pid_file = ::open("/proc/sys/kernel/core_uses_pid", O_RDONLY); if (core_uses_pid_file != -1) { @@ -6038,7 +6040,7 @@ ssize_t ret = ::read(core_uses_pid_file, &core_uses_pid, 1); ::close(core_uses_pid_file); - if (core_uses_pid == '1'){ + if (core_uses_pid == '1') { jio_snprintf(buffer + written, bufferSize - written, ".%d", current_process_id()); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/linux/vm/os_linux.hpp --- a/hotspot/src/os/linux/vm/os_linux.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -143,6 +143,7 @@ static int vm_default_page_size(void) { return _vm_default_page_size; } static address ucontext_get_pc(ucontext_t* uc); + static void ucontext_set_pc(ucontext_t* uc, address pc); static intptr_t* ucontext_get_sp(ucontext_t* uc); static intptr_t* ucontext_get_fp(ucontext_t* uc); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/linux/vm/vmError_linux.cpp --- a/hotspot/src/os/linux/vm/vmError_linux.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/linux/vm/vmError_linux.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -112,7 +112,16 @@ } pthread_sigmask(SIG_UNBLOCK, &newset, NULL); - VMError err(NULL, sig, NULL, info, ucVoid); + // support safefetch faults in error handling + ucontext_t* const uc = (ucontext_t*) ucVoid; + address const pc = uc ? os::Linux::ucontext_get_pc(uc) : NULL; + + if (uc && pc && StubRoutines::is_safefetch_fault(pc)) { + os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); + return; + } + + VMError err(NULL, sig, pc, info, ucVoid); err.report_and_die(); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/solaris/vm/os_solaris.hpp --- a/hotspot/src/os/solaris/vm/os_solaris.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -137,6 +137,7 @@ // ucontext_get_fp() is only used by Solaris X86 (see note below) static intptr_t* ucontext_get_fp(ucontext_t* uc); static address ucontext_get_pc(ucontext_t* uc); + static void ucontext_set_pc(ucontext_t* uc, address pc); // For Analyzer Forte AsyncGetCallTrace profiling support: // Parameter ret_fp is only used by Solaris X86. diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os/solaris/vm/vmError_solaris.cpp --- a/hotspot/src/os/solaris/vm/vmError_solaris.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os/solaris/vm/vmError_solaris.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -109,7 +109,15 @@ } thr_sigsetmask(SIG_UNBLOCK, &newset, NULL); - VMError err(NULL, sig, NULL, info, ucVoid); + // support safefetch faults in error handling + ucontext_t* const uc = (ucontext_t*) ucVoid; + address const pc = uc ? os::Solaris::ucontext_get_pc(uc) : NULL; + if (uc && pc && StubRoutines::is_safefetch_fault(pc)) { + os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); + return; + } + + VMError err(NULL, sig, pc, info, ucVoid); err.report_and_die(); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp --- a/hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. All rights reserved. * 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,5 @@ // Only used on 64 bit platforms define_pd_global(uintx,HeapBaseMinAddress, 2*G); -// Only used on 64 bit Windows platforms -define_pd_global(bool, UseVectoredExceptions, false); #endif // OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -397,7 +397,7 @@ // continue at the next instruction after the faulting read. Returning // garbage from this read is ok. thread->set_pending_unsafe_access_error(); - uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4; + os::Aix::ucontext_set_pc(uc, pc + 4); return 1; } } @@ -420,7 +420,7 @@ // continue at the next instruction after the faulting read. Returning // garbage from this read is ok. thread->set_pending_unsafe_access_error(); - uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4; + os::Aix::ucontext_set_pc(uc, pc + 4); return 1; } } @@ -445,7 +445,7 @@ if (stub != NULL) { // Save all thread context in case we need to restore it. if (thread != NULL) thread->set_saved_exception_pc(pc); - uc->uc_mcontext.jmp_context.iar = (unsigned long)stub; + os::Aix::ucontext_set_pc(uc, stub); return 1; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -309,6 +309,10 @@ return (address)uc->context_pc; } +void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) { + uc->context_pc = (intptr_t)pc ; +} + intptr_t* os::Bsd::ucontext_get_sp(ucontext_t * uc) { return (intptr_t*)uc->context_sp; } @@ -463,7 +467,7 @@ pc = (address) os::Bsd::ucontext_get_pc(uc); if (StubRoutines::is_safefetch_fault(pc)) { - uc->context_pc = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc)); + os::Bsd::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); return 1; } @@ -703,7 +707,7 @@ // save all thread context in case we need to restore it if (thread != NULL) thread->set_saved_exception_pc(pc); - uc->context_pc = (intptr_t)stub; + os::Bsd::ucontext_set_pc(uc, stub); return true; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -107,6 +107,10 @@ return NULL; } +void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) { + ShouldNotCallThis(); +} + ExtendedPC os::fetch_frame_from_context(void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp --- a/hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. All rights reserved. * 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,5 @@ // Only used on 64 bit platforms define_pd_global(uintx,HeapBaseMinAddress, 2*G); -// Only used on 64 bit Windows platforms -define_pd_global(bool, UseVectoredExceptions, false); #endif // OS_CPU_LINUX_PPC_VM_GLOBALS_LINUX_PPC_HPP diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -113,6 +113,14 @@ return (address)uc->uc_mcontext.regs->nip; } +// modify PC in ucontext. +// Note: Only use this for an ucontext handed down to a signal handler. See comment +// in ucontext_get_pc. +void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { + guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_set_pc in sigaction context"); + uc->uc_mcontext.regs->nip = (unsigned long)pc; +} + intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) { return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/]; } @@ -213,7 +221,7 @@ if (uc) { address const pc = os::Linux::ucontext_get_pc(uc); if (pc && StubRoutines::is_safefetch_fault(pc)) { - uc->uc_mcontext.regs->nip = (unsigned long)StubRoutines::continuation_for_safefetch_fault(pc); + os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); return true; } } @@ -360,7 +368,7 @@ // continue at the next instruction after the faulting read. Returning // garbage from this read is ok. thread->set_pending_unsafe_access_error(); - uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4; + os::Linux::ucontext_set_pc(uc, pc + 4); return true; } } @@ -379,7 +387,7 @@ // continue at the next instruction after the faulting read. Returning // garbage from this read is ok. thread->set_pending_unsafe_access_error(); - uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4; + os::Linux::ucontext_set_pc(uc, pc + 4); return true; } } @@ -402,7 +410,7 @@ if (stub != NULL) { // Save all thread context in case we need to restore it. if (thread != NULL) thread->set_saved_exception_pc(pc); - uc->uc_mcontext.regs->nip = (unsigned long)stub; + os::Linux::ucontext_set_pc(uc, stub); return true; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -85,11 +85,6 @@ CON_O7, }; -static inline void set_cont_address(sigcontext* ctx, address addr) { - SIG_PC(ctx) = (intptr_t)addr; - SIG_NPC(ctx) = (intptr_t)(addr+4); -} - // For Forte Analyzer AsyncGetCallTrace profiling support - thread is // currently interrupted by SIGPROF. // os::Solaris::fetch_frame_from_ucontext() tries to skip nested @@ -351,6 +346,12 @@ return (address) SIG_PC((sigcontext*)uc); } +void os::Linux::ucontext_set_pc(ucontext_t* uc, address pc) { + sigcontext_t* ctx = (sigcontext_t*) uc; + SIG_PC(ctx) = (intptr_t)addr; + SIG_NPC(ctx) = (intptr_t)(addr+4); +} + intptr_t* os::Linux::ucontext_get_sp(ucontext_t *uc) { return (intptr_t*) ((intptr_t)SIG_REGS((sigcontext*)uc).u_regs[CON_O6] + STACK_BIAS); @@ -366,7 +367,7 @@ inline static bool checkPrefetch(sigcontext* uc, address pc) { if (StubRoutines::is_safefetch_fault(pc)) { - set_cont_address(uc, address(StubRoutines::continuation_for_safefetch_fault(pc))); + os::Linux::ucontext_set_pc((ucontext_t*)uc, StubRoutines::continuation_for_safefetch_fault(pc)); return true; } return false; @@ -666,7 +667,7 @@ // save all thread context in case we need to restore it thread->set_saved_exception_pc(pc); thread->set_saved_exception_npc(npc); - set_cont_address(uc, stub); + os::Linux::ucontext_set_pc((ucontext_t*)uc, stub); return true; } } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -122,6 +122,10 @@ return (address)uc->uc_mcontext.gregs[REG_PC]; } +void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { + uc->uc_mcontext.gregs[REG_PC] = (intptr_t)pc; +} + intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) { return (intptr_t*)uc->uc_mcontext.gregs[REG_SP]; } @@ -279,7 +283,7 @@ pc = (address) os::Linux::ucontext_get_pc(uc); if (StubRoutines::is_safefetch_fault(pc)) { - uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc)); + os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); return 1; } @@ -514,7 +518,7 @@ // save all thread context in case we need to restore it if (thread != NULL) thread->set_saved_exception_pc(pc); - uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub; + os::Linux::ucontext_set_pc(uc, stub); return true; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -100,6 +100,10 @@ ShouldNotCallThis(); } +void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { + ShouldNotCallThis(); +} + ExtendedPC os::fetch_frame_from_context(void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -184,6 +184,11 @@ return ExtendedPC(pc); } +void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) { + uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc; + uc->uc_mcontext.gregs [REG_nPC] = (greg_t) (pc + 4); +} + // Assumes ucontext is valid intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) { return (intptr_t*)((intptr_t)uc->uc_mcontext.gregs[REG_SP] + STACK_BIAS); @@ -355,8 +360,7 @@ // SafeFetch() support if (StubRoutines::is_safefetch_fault(pc)) { - uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc)); - uc->uc_mcontext.gregs[REG_nPC] = uc->uc_mcontext.gregs[REG_PC] + 4; + os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); return 1; } @@ -494,8 +498,7 @@ // simulate a branch to the stub (a "call" in the safepoint stub case) // factor me: setPC - uc->uc_mcontext.gregs[REG_PC ] = (greg_t)stub; - uc->uc_mcontext.gregs[REG_nPC] = (greg_t)(stub + 4); + os::Solaris::ucontext_set_pc(uc, stub); #ifndef PRODUCT if (TraceJumps) thread->record_jump(stub, NULL, __FILE__, __LINE__); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -174,6 +174,10 @@ return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]); } +void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) { + uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc; +} + // Assumes ucontext is valid intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) { return (intptr_t*)uc->uc_mcontext.gregs[REG_SP]; @@ -411,7 +415,7 @@ pc = (address) uc->uc_mcontext.gregs[REG_PC]; if (StubRoutines::is_safefetch_fault(pc)) { - uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc)); + os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); return true; } @@ -614,8 +618,7 @@ if (thread != NULL) thread->set_saved_exception_pc(pc); // 12/02/99: On Sparc it appears that the full context is also saved // but as yet, no one looks at or restores that saved context - // factor me: setPC - uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub; + os::Solaris::ucontext_set_pc(uc, stub); return true; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/asm/codeBuffer.cpp --- a/hotspot/src/share/vm/asm/codeBuffer.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -926,9 +926,6 @@ void CodeBuffer::take_over_code_from(CodeBuffer* cb) { // Must already have disposed of the old blob somehow. assert(blob() == NULL, "must be empty"); -#ifdef ASSERT - -#endif // Take the new blob away from cb. set_blob(cb->blob()); // Take over all the section pointers. diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -4306,7 +4306,18 @@ log->inline_fail("reason unknown"); } } - +#if INCLUDE_TRACE + EventCompilerInlining event; + if (event.should_commit()) { + event.set_compileID(compilation()->env()->task()->compile_id()); + event.set_message(msg); + event.set_succeeded(success); + event.set_bci(bci()); + event.set_caller(method()->get_Method()); + event.set_callee(callee->to_trace_struct()); + event.commit(); + } +#endif // INCLUDE_TRACE if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) { return; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/ci/ciMethod.cpp --- a/hotspot/src/share/vm/ci/ciMethod.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -48,6 +48,7 @@ #include "runtime/deoptimization.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/xmlstream.hpp" +#include "trace/tracing.hpp" #ifdef COMPILER2 #include "ci/bcEscapeAnalyzer.hpp" #include "ci/ciTypeFlow.hpp" @@ -1466,3 +1467,13 @@ st->print(" loaded=false"); } } + +#if INCLUDE_TRACE +TraceStructCiMethod ciMethod::to_trace_struct() const { + TraceStructCiMethod result; + result.set_class(holder()->name()->as_utf8()); + result.set_name(name()->as_utf8()); + result.set_signature(signature()->as_symbol()->as_utf8()); + return result; +} +#endif diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/ci/ciMethod.hpp --- a/hotspot/src/share/vm/ci/ciMethod.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/ci/ciMethod.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -32,13 +32,14 @@ #include "compiler/methodLiveness.hpp" #include "prims/methodHandles.hpp" #include "utilities/bitMap.hpp" +#include "trace/tracing.hpp" class ciMethodBlocks; class MethodLiveness; class BitMap; class Arena; class BCEscapeAnalyzer; - +class InlineTree; // ciMethod // @@ -52,6 +53,7 @@ friend class ciBytecodeStream; friend class ciMethodHandle; friend class ciReplay; + friend class InlineTree; private: // General method information. @@ -95,12 +97,6 @@ ciMethod(methodHandle h_m, ciInstanceKlass* holder); ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); - Method* get_Method() const { - Method* m = (Method*)_metadata; - assert(m != NULL, "illegal use of unloaded method"); - return m; - } - oop loader() const { return _holder->loader(); } const char* type_string() { return "ciMethod"; } @@ -158,6 +154,11 @@ } } + Method* get_Method() const { + Method* m = (Method*)_metadata; + assert(m != NULL, "illegal use of unloaded method"); + return m; + } // Method code and related information. address code() { if (_code == NULL) load_code(); return _code; } @@ -339,6 +340,10 @@ // Print the name of this method in various incarnations. void print_name(outputStream* st = tty); void print_short_name(outputStream* st = tty); + +#if INCLUDE_TRACE + TraceStructCiMethod to_trace_struct() const; +#endif }; #endif // SHARE_VM_CI_CIMETHOD_HPP diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -467,6 +467,12 @@ } else { ShouldNotReachHere(); } + } else { + // Metadata is alive. + // If scratch_class is on stack then it shouldn't be on this list! + assert(!m->is_klass() || !((InstanceKlass*)m)->is_scratch_class(), + "scratch classes on this list should be dead"); + // Also should assert that other metadata on the list was found in handles. } } } @@ -737,11 +743,22 @@ // Move class loader data from main list to the unloaded list for unloading // and deallocation later. -bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, bool clean_alive) { +bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, + bool clean_previous_versions) { + ClassLoaderData* data = _head; ClassLoaderData* prev = NULL; bool seen_dead_loader = false; + // Mark metadata seen on the stack only so we can delete unneeded entries. + // Only walk all metadata, including the expensive code cache walk, for Full GC + // and only if class redefinition and if there's previous versions of + // Klasses to delete. + bool walk_all_metadata = clean_previous_versions && + JvmtiExport::has_redefined_a_class() && + InstanceKlass::has_previous_versions(); + MetadataOnStackMark md_on_stack(walk_all_metadata); + // Save previous _unloading pointer for CMS which may add to unloading list before // purging and we don't want to rewalk the previously unloaded class loader data. _saved_unloading = _unloading; @@ -749,6 +766,11 @@ data = _head; while (data != NULL) { if (data->is_alive(is_alive_closure)) { + // clean metaspace + if (walk_all_metadata) { + data->classes_do(InstanceKlass::purge_previous_versions); + } + data->free_deallocate_list(); prev = data; data = data->next(); continue; @@ -770,11 +792,6 @@ _unloading = dead; } - if (clean_alive) { - // Clean previous versions and the deallocate list. - ClassLoaderDataGraph::clean_metaspaces(); - } - if (seen_dead_loader) { post_class_unload_events(); } @@ -782,21 +799,6 @@ return seen_dead_loader; } -void ClassLoaderDataGraph::clean_metaspaces() { - // mark metadata seen on the stack and code cache so we can delete unneeded entries. - bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); - MetadataOnStackMark md_on_stack(has_redefined_a_class); - - if (has_redefined_a_class) { - for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { - data->classes_do(InstanceKlass::purge_previous_versions); - } - } - - // Should purge the previous version before deallocating. - free_deallocate_lists(); -} - void ClassLoaderDataGraph::purge() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); ClassLoaderData* list = _unloading; @@ -829,12 +831,6 @@ #endif } -void ClassLoaderDataGraph::free_deallocate_lists() { - for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { - cld->free_deallocate_list(); - } -} - // CDS support // Global metaspaces for writing information to the shared archive. When diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -75,7 +75,6 @@ static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); static void post_class_unload_events(void); - static void clean_metaspaces(); public: static ClassLoaderData* find_or_create(Handle class_loader, TRAPS); static void purge(); @@ -95,7 +94,7 @@ static void methods_do(void f(Method*)); static void loaded_classes_do(KlassClosure* klass_closure); static void classes_unloading_do(void f(Klass* const)); - static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive); + static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions); // CMS support. static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); } @@ -114,8 +113,6 @@ static bool has_metaspace_oom() { return _metaspace_oom; } static void set_metaspace_oom(bool value) { _metaspace_oom = value; } - static void free_deallocate_lists(); - static void dump_on(outputStream * const out) PRODUCT_RETURN; static void dump() { dump_on(tty); } static void verify(); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/classfile/metadataOnStackMark.cpp --- a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -33,26 +33,31 @@ #include "services/threadService.hpp" #include "utilities/chunkedList.hpp" -volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL; -volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL; +MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL; +MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL; +MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = NULL; NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) // Walk metadata on the stack and mark it so that redefinition doesn't delete -// it. Class unloading also walks the previous versions and might try to -// delete it, so this class is used by class unloading also. -MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) { +// it. Class unloading only deletes in-error class files, methods created by +// the relocator and dummy constant pools. None of these appear anywhere except +// in metadata Handles. +MetadataOnStackMark::MetadataOnStackMark(bool redefinition_walk) { assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); assert(_used_buffers == NULL, "sanity check"); + assert(!_is_active, "MetadataOnStackMarks do not nest"); NOT_PRODUCT(_is_active = true;) - Threads::metadata_do(Metadata::mark_on_stack); - if (visit_code_cache) { + Threads::metadata_handles_do(Metadata::mark_on_stack); + + if (redefinition_walk) { + Threads::metadata_do(Metadata::mark_on_stack); CodeCache::alive_nmethods_do(nmethod::mark_on_stack); + CompileBroker::mark_on_stack(); + JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack); + ThreadService::metadata_do(Metadata::mark_on_stack); } - CompileBroker::mark_on_stack(); - JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack); - ThreadService::metadata_do(Metadata::mark_on_stack); } MetadataOnStackMark::~MetadataOnStackMark() { @@ -60,10 +65,9 @@ // Unmark everything that was marked. Can't do the same walk because // redefine classes messes up the code cache so the set of methods // might not be the same. + retire_current_buffer(); - retire_buffer_for_thread(Thread::current()); - - MetadataOnStackBuffer* buffer = const_cast(_used_buffers); + MetadataOnStackBuffer* buffer = _used_buffers; while (buffer != NULL) { // Clear on stack state for all metadata. size_t size = buffer->size(); @@ -77,7 +81,7 @@ // Move the buffer to the free list. buffer->clear(); buffer->set_next_used(NULL); - buffer->set_next_free(const_cast(_free_buffers)); + buffer->set_next_free(_free_buffers); _free_buffers = buffer; // Step to next used buffer. @@ -93,35 +97,23 @@ if (buffer == NULL) { return; } - - MetadataOnStackBuffer* old_head; - - do { - old_head = const_cast(_used_buffers); - buffer->set_next_used(old_head); - } while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head); -} - -void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) { - retire_buffer(thread->metadata_on_stack_buffer()); - thread->set_metadata_on_stack_buffer(NULL); + buffer->set_next_used(_used_buffers); + _used_buffers = buffer; } -bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) { - return thread->metadata_on_stack_buffer() != NULL; +// Current buffer is full or we're ready to walk them, add it to the used list. +void MetadataOnStackMark::retire_current_buffer() { + retire_buffer(_current_buffer); + _current_buffer = NULL; } +// Get buffer off free list. MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() { - MetadataOnStackBuffer* allocated; - MetadataOnStackBuffer* new_head; + MetadataOnStackBuffer* allocated = _free_buffers; - do { - allocated = const_cast(_free_buffers); - if (allocated == NULL) { - break; - } - new_head = allocated->next_free(); - } while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated); + if (allocated != NULL) { + _free_buffers = allocated->next_free(); + } if (allocated == NULL) { allocated = new MetadataOnStackBuffer(); @@ -133,10 +125,10 @@ } // Record which objects are marked so we can unmark the same objects. -void MetadataOnStackMark::record(Metadata* m, Thread* thread) { +void MetadataOnStackMark::record(Metadata* m) { assert(_is_active, "metadata on stack marking is active"); - MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer(); + MetadataOnStackBuffer* buffer = _current_buffer; if (buffer != NULL && buffer->is_full()) { retire_buffer(buffer); @@ -145,7 +137,7 @@ if (buffer == NULL) { buffer = allocate_buffer(); - thread->set_metadata_on_stack_buffer(buffer); + _current_buffer = buffer; } buffer->push(m); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/classfile/metadataOnStackMark.hpp --- a/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -36,23 +36,23 @@ // or executing methods, so that it can't be deleted during class redefinition // and class unloading. // This is also used for other things that can be deallocated, like class -// metadata during parsing, relocated methods, and methods in backtraces. +// metadata during parsing if errors occur, relocated methods, and temporary +// constant pools. class MetadataOnStackMark : public StackObj { NOT_PRODUCT(static bool _is_active;) - - static volatile MetadataOnStackBuffer* _used_buffers; - static volatile MetadataOnStackBuffer* _free_buffers; + static MetadataOnStackBuffer* _used_buffers; + static MetadataOnStackBuffer* _free_buffers; + static MetadataOnStackBuffer* _current_buffer; static MetadataOnStackBuffer* allocate_buffer(); static void retire_buffer(MetadataOnStackBuffer* buffer); public: - MetadataOnStackMark(bool visit_code_cache); + MetadataOnStackMark(bool redefinition_walk); ~MetadataOnStackMark(); - static void record(Metadata* m, Thread* thread); - static void retire_buffer_for_thread(Thread* thread); - static bool has_buffer_for_thread(Thread* thread); + static void record(Metadata* m); + static void retire_current_buffer(); }; #endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1368,8 +1368,6 @@ ClassLoaderData* loader_data = k->class_loader_data(); Handle class_loader_h(THREAD, loader_data->class_loader()); - for (uintx it = 0; it < GCExpandToAllocateDelayMillis; it++){} - // for bootstrap and other parallel classloaders don't acquire lock, // use placeholder token // If a parallelCapable class loader calls define_instance_class instead of @@ -1690,9 +1688,11 @@ // Assumes classes in the SystemDictionary are only unloaded at a safepoint // Note: anonymous classes are not in the SD. -bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive, bool clean_alive) { +bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive, + bool clean_previous_versions) { // First, mark for unload all ClassLoaderData referencing a dead class loader. - bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive, clean_alive); + bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive, + clean_previous_versions); if (unloading_occurred) { dictionary()->do_unloading(); constraints()->purge_loader_constraints(); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/classfile/systemDictionary.hpp --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -335,7 +335,8 @@ // Unload (that is, break root links to) all unmarked classes and // loaders. Returns "true" iff something was unloaded. - static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive = true); + static bool do_unloading(BoolObjectClosure* is_alive, + bool clean_previous_versions = true); // Used by DumpSharedSpaces only to remove classes that failed verification static void remove_classes_in_error_state(); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1572,17 +1572,12 @@ set_unload_reported(); } -void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive, bool mark_on_stack) { +void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) { if (ic->is_icholder_call()) { // The only exception is compiledICHolder oops which may // yet be marked below. (We check this further below). CompiledICHolder* cichk_oop = ic->cached_icholder(); - if (mark_on_stack) { - Metadata::mark_on_stack(cichk_oop->holder_method()); - Metadata::mark_on_stack(cichk_oop->holder_klass()); - } - if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && cichk_oop->holder_klass()->is_loader_alive(is_alive)) { return; @@ -1590,10 +1585,6 @@ } else { Metadata* ic_oop = ic->cached_metadata(); if (ic_oop != NULL) { - if (mark_on_stack) { - Metadata::mark_on_stack(ic_oop); - } - if (ic_oop->is_klass()) { if (((Klass*)ic_oop)->is_loader_alive(is_alive)) { return; @@ -1634,8 +1625,7 @@ // The RedefineClasses() API can cause the class unloading invariant // to no longer be true. See jvmtiExport.hpp for details. // Also, leave a debugging breadcrumb in local flag. - bool a_class_was_redefined = JvmtiExport::has_redefined_a_class(); - if (a_class_was_redefined) { + if (JvmtiExport::has_redefined_a_class()) { // This set of the unloading_occurred flag is done before the // call to post_compiled_method_unload() so that the unloading // of this nmethod is reported. @@ -1654,7 +1644,7 @@ while(iter.next()) { if (iter.type() == relocInfo::virtual_call_type) { CompiledIC *ic = CompiledIC_at(&iter); - clean_ic_if_metadata_is_dead(ic, is_alive, false); + clean_ic_if_metadata_is_dead(ic, is_alive); } } } @@ -1741,33 +1731,6 @@ return false; } -void nmethod::mark_metadata_on_stack_at(RelocIterator* iter_at_metadata) { - assert(iter_at_metadata->type() == relocInfo::metadata_type, "Wrong relocation type"); - - metadata_Relocation* r = iter_at_metadata->metadata_reloc(); - // In this metadata, we must only follow those metadatas directly embedded in - // the code. Other metadatas (oop_index>0) are seen as part of - // the metadata section below. - assert(1 == (r->metadata_is_immediate()) + - (r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()), - "metadata must be found in exactly one place"); - if (r->metadata_is_immediate() && r->metadata_value() != NULL) { - Metadata* md = r->metadata_value(); - if (md != _method) Metadata::mark_on_stack(md); - } -} - -void nmethod::mark_metadata_on_stack_non_relocs() { - // Visit the metadata section - for (Metadata** p = metadata_begin(); p < metadata_end(); p++) { - if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops - Metadata* md = *p; - Metadata::mark_on_stack(md); - } - - // Visit metadata not embedded in the other places. - if (_method != NULL) Metadata::mark_on_stack(_method); -} bool nmethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) { ResourceMark rm; @@ -1790,19 +1753,13 @@ // The RedefineClasses() API can cause the class unloading invariant // to no longer be true. See jvmtiExport.hpp for details. // Also, leave a debugging breadcrumb in local flag. - bool a_class_was_redefined = JvmtiExport::has_redefined_a_class(); - if (a_class_was_redefined) { + if (JvmtiExport::has_redefined_a_class()) { // This set of the unloading_occurred flag is done before the // call to post_compiled_method_unload() so that the unloading // of this nmethod is reported. unloading_occurred = true; } - // When class redefinition is used all metadata in the CodeCache has to be recorded, - // so that unused "previous versions" can be purged. Since walking the CodeCache can - // be expensive, the "mark on stack" is piggy-backed on this parallel unloading code. - bool mark_metadata_on_stack = a_class_was_redefined; - // Exception cache clean_exception_cache(is_alive); @@ -1818,7 +1775,7 @@ if (unloading_occurred) { // If class unloading occurred we first iterate over all inline caches and // clear ICs where the cached oop is referring to an unloaded klass or method. - clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive, mark_metadata_on_stack); + clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive); } postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this); @@ -1839,16 +1796,10 @@ break; case relocInfo::metadata_type: - if (mark_metadata_on_stack) { - mark_metadata_on_stack_at(&iter); - } + break; // nothing to do. } } - if (mark_metadata_on_stack) { - mark_metadata_on_stack_non_relocs(); - } - if (is_unloaded) { return postponed; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/code/nmethod.hpp --- a/hotspot/src/share/vm/code/nmethod.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/code/nmethod.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -593,9 +593,6 @@ bool can_unload(BoolObjectClosure* is_alive, oop* root, bool unloading_occurred); bool unload_if_dead_at(RelocIterator *iter_at_oop, BoolObjectClosure* is_alive, bool unloading_occurred); - void mark_metadata_on_stack_at(RelocIterator* iter_at_metadata); - void mark_metadata_on_stack_non_relocs(); - public: void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -2170,12 +2170,13 @@ g1h->secondary_free_list_add(&tmp_free_list); SecondaryFreeList_lock->notify_all(); } - +#ifndef PRODUCT if (G1StressConcRegionFreeing) { for (uintx i = 0; i < G1StressConcRegionFreeingDelayMillis; ++i) { os::sleep(Thread::current(), (jlong) 1, false); } } +#endif } } assert(tmp_free_list.is_empty(), "post-condition"); @@ -2532,11 +2533,6 @@ G1CMTraceTime trace("Unloading", G1Log::finer()); if (ClassUnloadingWithConcurrentMark) { - // Cleaning of klasses depends on correct information from MetadataMarkOnStack. The CodeCache::mark_on_stack - // part is too slow to be done serially, so it is handled during the weakRefsWorkParallelPart phase. - // Defer the cleaning until we have complete on_stack data. - MetadataOnStackMark md_on_stack(false /* Don't visit the code cache at this point */); - bool purged_classes; { @@ -2548,11 +2544,6 @@ G1CMTraceTime trace("Parallel Unloading", G1Log::finest()); weakRefsWorkParallelPart(&g1_is_alive, purged_classes); } - - { - G1CMTraceTime trace("Deallocate Metadata", G1Log::finest()); - ClassLoaderDataGraph::free_deallocate_lists(); - } } if (G1StringDedup::is_enabled()) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -853,7 +853,7 @@ // Returns the card bitmap for a given task or worker id. BitMap* count_card_bitmap_for(uint worker_id) { - assert(0 <= worker_id && worker_id < _max_worker_id, "oob"); + assert(worker_id < _max_worker_id, "oob"); assert(_count_card_bitmaps != NULL, "uninitialized"); BitMap* task_card_bm = &_count_card_bitmaps[worker_id]; assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); @@ -863,7 +863,7 @@ // Returns the array containing the marked bytes for each region, // for the given worker or task id. size_t* count_marked_bytes_array_for(uint worker_id) { - assert(0 <= worker_id && worker_id < _max_worker_id, "oob"); + assert(worker_id < _max_worker_id, "oob"); assert(_count_marked_bytes != NULL, "uninitialized"); size_t* marked_bytes_array = _count_marked_bytes[worker_id]; assert(marked_bytes_array != NULL, "uninitialized"); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -84,13 +84,13 @@ "_ct_bot: " PTR_FORMAT, p2i(card_ptr), p2i(_ct_bot))); size_t card_num = pointer_delta(card_ptr, _ct_bot, sizeof(jbyte)); - assert(card_num >= 0 && card_num < _reserved_max_card_num, + assert(card_num < _reserved_max_card_num, err_msg("card pointer out of range: " PTR_FORMAT, p2i(card_ptr))); return card_num; } jbyte* card_num_2_ptr(size_t card_num) { - assert(card_num >= 0 && card_num < _reserved_max_card_num, + assert(card_num < _reserved_max_card_num, err_msg("card num out of range: "SIZE_FORMAT, card_num)); return (jbyte*) (_ct_bot + card_num); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -4909,10 +4909,6 @@ clean_nmethod(claimed_nmethods[i]); } } - - // The nmethod cleaning helps out and does the CodeCache part of MetadataOnStackMark. - // Need to retire the buffers now that this thread has stopped cleaning nmethods. - MetadataOnStackMark::retire_buffer_for_thread(Thread::current()); } void work_second_pass(uint worker_id) { @@ -4965,9 +4961,6 @@ // G1 specific cleanup work that has // been moved here to be done in parallel. ik->clean_dependent_nmethods(); - if (JvmtiExport::has_redefined_a_class()) { - InstanceKlass::purge_previous_versions(ik); - } } void work() { @@ -5002,18 +4995,8 @@ _klass_cleaning_task(is_alive) { } - void pre_work_verification() { - assert(!MetadataOnStackMark::has_buffer_for_thread(Thread::current()), "Should be empty"); - } - - void post_work_verification() { - assert(!MetadataOnStackMark::has_buffer_for_thread(Thread::current()), "Should be empty"); - } - // The parallel work done by all worker threads. void work(uint worker_id) { - pre_work_verification(); - // Do first pass of code cache cleaning. _code_cache_task.work_first_pass(worker_id); @@ -5032,8 +5015,6 @@ // Clean all klasses that were not unloaded. _klass_cleaning_task.work(); - - post_work_verification(); } }; @@ -5425,7 +5406,7 @@ // limit is set using max_num_q() - which was set using ParallelGCThreads. // So this must be true - but assert just in case someone decides to // change the worker ids. - assert(0 <= worker_id && worker_id < limit, "sanity"); + assert(worker_id < limit, "sanity"); assert(!rp->discovery_is_atomic(), "check this code"); // Select discovered lists [i, i+stride, i+2*stride,...,limit) diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -324,9 +324,8 @@ void HeapRegion::note_self_forwarding_removal_end(bool during_initial_mark, bool during_conc_mark, size_t marked_bytes) { - assert(0 <= marked_bytes && marked_bytes <= used(), - err_msg("marked: "SIZE_FORMAT" used: "SIZE_FORMAT, - marked_bytes, used())); + assert(marked_bytes <= used(), + err_msg("marked: "SIZE_FORMAT" used: "SIZE_FORMAT, marked_bytes, used())); _prev_top_at_mark_start = top(); _prev_marked_bytes = marked_bytes; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -270,7 +270,7 @@ const uint n_regions = hrclaimer->n_regions(); for (uint count = 0; count < n_regions; count++) { const uint index = (start_index + count) % n_regions; - assert(0 <= index && index < n_regions, "sanity"); + assert(index < n_regions, "sanity"); // Skip over unavailable regions if (!is_available(index)) { continue; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -541,7 +541,7 @@ PerRegionTable* OtherRegionsTable::find_region_table(size_t ind, HeapRegion* hr) const { - assert(0 <= ind && ind < _max_fine_entries, "Preconditions."); + assert(ind < _max_fine_entries, "Preconditions."); PerRegionTable* prt = _fine_grain_regions[ind]; while (prt != NULL && prt->hr() != hr) { prt = prt->collision_list_next(); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ check_mt_safety(); guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) || - (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0), + (!is_empty() && length() > 0 && total_capacity_bytes() > 0) , hrs_ext_msg(this, "invariant")); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -58,7 +58,7 @@ void PtrQueue::enqueue_known_active(void* ptr) { - assert(0 <= _index && _index <= _sz, "Invariant."); + assert(_index <= _sz, "Invariant."); assert(_index == 0 || _buf != NULL, "invariant"); while (_index == 0) { @@ -68,7 +68,7 @@ assert(_index > 0, "postcondition"); _index -= oopSize; _buf[byte_index_to_index((int)_index)] = ptr; - assert(0 <= _index && _index <= _sz, "Invariant."); + assert(_index <= _sz, "Invariant."); } void PtrQueue::locking_enqueue_completed_buffer(void** buf) { @@ -194,7 +194,6 @@ _buf = qset()->allocate_buffer(); _sz = qset()->buffer_size(); _index = _sz; - assert(0 <= _index && _index <= _sz, "Invariant."); } bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,8 +195,9 @@ // our closures depend on this property and do not protect against // double scans. - uintptr_t cur_chunk_index = addr_to_chunk_index(chunk_mr.start()); - cur_chunk_index = cur_chunk_index - lowest_non_clean_base_chunk_index; + uintptr_t start_chunk_index = addr_to_chunk_index(chunk_mr.start()); + assert(start_chunk_index >= lowest_non_clean_base_chunk_index, "Bounds error."); + uintptr_t cur_chunk_index = start_chunk_index - lowest_non_clean_base_chunk_index; NOISY(tty->print_cr("===========================================================================");) NOISY(tty->print_cr(" process_chunk_boundary: Called with [" PTR_FORMAT "," PTR_FORMAT ")", @@ -242,8 +243,7 @@ if (first_dirty_card != NULL) { NOISY(tty->print_cr(" LNC: Found a dirty card at " PTR_FORMAT " in current chunk", first_dirty_card);) - assert(0 <= cur_chunk_index && cur_chunk_index < lowest_non_clean_chunk_size, - "Bounds error."); + assert(cur_chunk_index < lowest_non_clean_chunk_size, "Bounds error."); assert(lowest_non_clean[cur_chunk_index] == NULL, "Write exactly once : value should be stable hereafter for this round"); lowest_non_clean[cur_chunk_index] = first_dirty_card; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -103,7 +103,7 @@ static inline float exp_avg(float avg, float sample, unsigned int weight) { - assert(0 <= weight && weight <= 100, "weight must be a percent"); + assert(weight <= 100, "weight must be a percent"); return (100.0F - weight) * avg / 100.0F + weight * sample / 100.0F; } static inline size_t exp_avg(size_t avg, size_t sample, diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/shared/liveRange.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/liveRange.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/liveRange.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, 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 @@ -42,7 +42,6 @@ MemRegion::set_end(e); } void set_word_size(size_t ws) { - assert(ws >= 0, "should be a non-zero range"); MemRegion::set_word_size(ws); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -36,8 +36,7 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) { - assert(MutableSpace::alignment() >= 0 && - MutableSpace::alignment() % os::vm_page_size() == 0, + assert(MutableSpace::alignment() % os::vm_page_size() == 0, "Space should be aligned"); _mangler = new MutableSpaceMangler(this); } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/memory/allocation.cpp --- a/hotspot/src/share/vm/memory/allocation.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/memory/allocation.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -562,7 +562,6 @@ // Reallocate storage in Arena. void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size, AllocFailType alloc_failmode) { - assert(new_size >= 0, "bad size"); if (new_size == 0) return NULL; #ifdef ASSERT if (UseMallocOnly) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/memory/blockOffsetTable.cpp --- a/hotspot/src/share/vm/memory/blockOffsetTable.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/memory/blockOffsetTable.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -792,6 +792,5 @@ } size_t BlockOffsetArrayContigSpace::last_active_index() const { - size_t result = _next_offset_index - 1; - return result >= 0 ? result : 0; + return _next_offset_index == 0 ? 0 : _next_offset_index - 1; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/memory/heap.cpp --- a/hotspot/src/share/vm/memory/heap.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/memory/heap.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -52,7 +52,7 @@ void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { - assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); + assert( beg < _number_of_committed_segments, "interval begin out of bounds"); assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); // setup _segmap pointers for faster indexing address p = (address)_segmap.low() + beg; @@ -63,7 +63,7 @@ void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { - assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); + assert( beg < _number_of_committed_segments, "interval begin out of bounds"); assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); // setup _segmap pointers for faster indexing address p = (address)_segmap.low() + beg; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/memory/referenceProcessor.cpp --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -987,7 +987,7 @@ id = next_id(); } } - assert(0 <= id && id < _max_num_q, "Id is out-of-bounds (call Freud?)"); + assert(id < _max_num_q, "Id is out-of-bounds (call Freud?)"); // Get the discovered queue to which we will add DiscoveredList* list = NULL; @@ -1345,7 +1345,7 @@ } const char* ReferenceProcessor::list_name(uint i) { - assert(i >= 0 && i <= _max_num_q * number_of_subclasses_of_ref(), + assert(i <= _max_num_q * number_of_subclasses_of_ref(), "Out of bounds index"); int j = i / _max_num_q; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/oops/constantPool.cpp --- a/hotspot/src/share/vm/oops/constantPool.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/oops/constantPool.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1790,17 +1790,10 @@ void ConstantPool::set_on_stack(const bool value) { if (value) { - int old_flags = *const_cast(&_flags); - while ((old_flags & _on_stack) == 0) { - int new_flags = old_flags | _on_stack; - int result = Atomic::cmpxchg(new_flags, &_flags, old_flags); - - if (result == old_flags) { - // Succeeded. - MetadataOnStackMark::record(this, Thread::current()); - return; - } - old_flags = result; + // Only record if it's not already set. + if (!on_stack()) { + _flags |= _on_stack; + MetadataOnStackMark::record(this); } } else { // Clearing is done single-threadedly. diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -3492,9 +3492,11 @@ #endif + // RedefineClasses() support for previous versions: - -// Purge previous versions +int InstanceKlass::_previous_version_count = 0; + +// Purge previous versions before adding new previous versions of the class. void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { if (ik->previous_versions() != NULL) { // This klass has previous versions so see what we can cleanup @@ -3524,6 +3526,11 @@ // are executing. Unlink this previous_version. // The previous version InstanceKlass is on the ClassLoaderData deallocate list // so will be deallocated during the next phase of class unloading. + RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is dead", + pv_node)); + // For debugging purposes. + pv_node->set_is_scratch_class(); + pv_node->class_loader_data()->add_to_deallocate_list(pv_node); pv_node = pv_node->previous_versions(); last->link_previous_versions(pv_node); deleted_count++; @@ -3537,7 +3544,7 @@ live_count++; } - // At least one method is live in this previous version so clean its MethodData. + // At least one method is live in this previous version. // Reset dead EMCP methods not to get breakpoints. // All methods are deallocated when all of the methods for this class are no // longer running. @@ -3561,12 +3568,6 @@ ("purge: %s(%s): prev method @%d in version @%d is alive", method->name()->as_C_string(), method->signature()->as_C_string(), j, version)); -#ifdef ASSERT - if (method->method_data() != NULL) { - // Verify MethodData for running methods don't refer to old methods. - method->method_data()->verify_clean_weak_method_links(); - } -#endif // ASSERT } } } @@ -3579,18 +3580,6 @@ ("purge: previous version stats: live=%d, deleted=%d", live_count, deleted_count)); } - -#ifdef ASSERT - // Verify clean MethodData for this class's methods, e.g. they don't refer to - // old methods that are no longer running. - Array* methods = ik->methods(); - int num_methods = methods->length(); - for (int index = 0; index < num_methods; ++index) { - if (methods->at(index)->method_data() != NULL) { - methods->at(index)->method_data()->verify_clean_weak_method_links(); - } - } -#endif // ASSERT } void InstanceKlass::mark_newly_obsolete_methods(Array* old_methods, @@ -3677,6 +3666,11 @@ ConstantPool* cp_ref = scratch_class->constants(); if (!cp_ref->on_stack()) { RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running")); + // For debugging purposes. + scratch_class->set_is_scratch_class(); + scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class()); + // Update count for class unloading. + _previous_version_count--; return; } @@ -3688,8 +3682,8 @@ // if EMCP method (not obsolete) is on the stack, mark as EMCP so that // we can add breakpoints for it. - // We set the method->on_stack bit during safepoints for class redefinition and - // class unloading and use this bit to set the is_running_emcp bit. + // We set the method->on_stack bit during safepoints for class redefinition + // and use this bit to set the is_running_emcp bit. // After the safepoint, the on_stack bit is cleared and the running emcp // method may exit. If so, we would set a breakpoint in a method that // is never reached, but this won't be noticeable to the programmer. @@ -3708,6 +3702,8 @@ assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); scratch_class->link_previous_versions(previous_versions()); link_previous_versions(scratch_class()); + // Update count for class unloading. + _previous_version_count++; } // end add_previous_version() diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -206,7 +206,8 @@ _misc_is_contended = 1 << 4, // marked with contended annotation _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access) - _misc_has_been_redefined = 1 << 7 // class has been redefined + _misc_has_been_redefined = 1 << 7, // class has been redefined + _misc_is_scratch_class = 1 << 8 // class is the redefined scratch class }; u2 _misc_flags; u2 _minor_version; // minor version number of class file @@ -626,11 +627,23 @@ _misc_flags |= _misc_has_been_redefined; } + bool is_scratch_class() const { + return (_misc_flags & _misc_is_scratch_class) != 0; + } + + void set_is_scratch_class() { + _misc_flags |= _misc_is_scratch_class; + } + void init_previous_versions() { _previous_versions = NULL; } + private: + static int _previous_version_count; + public: static void purge_previous_versions(InstanceKlass* ik); + static bool has_previous_versions() { return _previous_version_count > 0; } // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation void set_cached_class_file(JvmtiCachedClassFileData *data) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/oops/method.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1970,9 +1970,10 @@ // on stack means some method referring to it is also on the stack. constants()->set_on_stack(value); - bool succeeded = _access_flags.set_on_stack(value); - if (value && succeeded) { - MetadataOnStackMark::record(this, Thread::current()); + bool already_set = on_stack(); + _access_flags.set_on_stack(value); + if (value && !already_set) { + MetadataOnStackMark::record(this); } } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/opto/bytecodeInfo.cpp --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -33,6 +33,7 @@ #include "opto/callGenerator.hpp" #include "opto/parse.hpp" #include "runtime/handles.inline.hpp" +#include "utilities/events.hpp" //============================================================================= //------------------------------InlineTree------------------------------------- @@ -490,7 +491,7 @@ //------------------------------print_inlining--------------------------------- void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, - bool success) const { + ciMethod* caller_method, bool success) const { const char* inline_msg = msg(); assert(inline_msg != NULL, "just checking"); if (C->log() != NULL) { @@ -509,6 +510,18 @@ //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); } } +#if INCLUDE_TRACE + EventCompilerInlining event; + if (event.should_commit()) { + event.set_compileID(C->compile_id()); + event.set_message(inline_msg); + event.set_succeeded(success); + event.set_bci(caller_bci); + event.set_caller(caller_method->get_Method()); + event.set_callee(callee_method->to_trace_struct()); + event.commit(); + } +#endif // INCLUDE_TRACE } //------------------------------ok_to_inline----------------------------------- @@ -531,14 +544,14 @@ // Do some initial checks. if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { set_msg("failed initial checks"); - print_inlining(callee_method, caller_bci, false /* !success */); + print_inlining(callee_method, caller_bci, caller_method, false /* !success */); return NULL; } // Do some parse checks. set_msg(check_can_parse(callee_method)); if (msg() != NULL) { - print_inlining(callee_method, caller_bci, false /* !success */); + print_inlining(callee_method, caller_bci, caller_method, false /* !success */); return NULL; } @@ -580,10 +593,11 @@ if (msg() == NULL) { set_msg("inline (hot)"); } - print_inlining(callee_method, caller_bci, true /* success */); + print_inlining(callee_method, caller_bci, caller_method, true /* success */); build_inline_tree_for_callee(callee_method, jvms, caller_bci); - if (InlineWarmCalls && !wci.is_hot()) + if (InlineWarmCalls && !wci.is_hot()) { return new (C) WarmCallInfo(wci); // copy to heap + } return WarmCallInfo::always_hot(); } @@ -591,7 +605,7 @@ if (msg() == NULL) { set_msg("too cold to inline"); } - print_inlining(callee_method, caller_bci, false /* !success */ ); + print_inlining(callee_method, caller_bci, caller_method, false /* !success */ ); return NULL; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/opto/chaitin.cpp --- a/hotspot/src/share/vm/opto/chaitin.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/opto/chaitin.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -602,7 +602,7 @@ // This frame must preserve the required fp alignment _framesize = round_to(_framesize, Matcher::stack_alignment_in_slots()); - assert( _framesize >= 0 && _framesize <= 1000000, "sanity check" ); + assert(_framesize <= 1000000, "sanity check"); #ifndef PRODUCT _total_framesize += _framesize; if ((int)_framesize > _max_framesize) { diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -3027,12 +3027,7 @@ // We may not have profiling here or it may not help us. If we have // a speculative type use it to perform an exact cast. ciKlass* spec_obj_type = obj_type->speculative_type(); - if (spec_obj_type != NULL || - (data != NULL && - // Counter has never been decremented (due to cast failure). - // ...This is a reasonable thing to expect. It is true of - // all casts inserted by javac to implement generic types. - data->as_CounterData()->count() >= 0)) { + if (spec_obj_type != NULL || data != NULL) { cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk->klass(), spec_obj_type, safe_for_replace); if (cast_obj != NULL) { if (failure_control != NULL) // failure is now impossible diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/opto/parse.hpp --- a/hotspot/src/share/vm/opto/parse.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/opto/parse.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -87,7 +87,7 @@ JVMState* jvms, WarmCallInfo* wci_result); void print_inlining(ciMethod* callee_method, int caller_bci, - bool success) const; + ciMethod* caller_method, bool success) const; InlineTree* caller_tree() const { return _caller_tree; } InlineTree* callee_at(int bci, ciMethod* m) const; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -142,14 +142,11 @@ for (int i = 0; i < _class_count; i++) { redefine_single_class(_class_defs[i].klass, _scratch_classes[i], thread); - ClassLoaderData* cld = _scratch_classes[i]->class_loader_data(); - // Free the memory for this class at class unloading time. Not before - // because CMS might think this is still live. - cld->add_to_deallocate_list((InstanceKlass*)_scratch_classes[i]); - _scratch_classes[i] = NULL; } // Clean out MethodData pointing to old Method* + // Have to do this after all classes are redefined and all methods that + // are redefined are marked as old. MethodDataCleaner clean_weak_method_links; ClassLoaderDataGraph::classes_do(&clean_weak_method_links); @@ -2902,18 +2899,13 @@ // } assert(stackmap_p + 1 <= stackmap_end, "no room for frame_type"); - // The Linux compiler does not like frame_type to be u1 or u2. It - // issues the following warning for the first if-statement below: - // - // "warning: comparison is always true due to limited range of data type" - // - u4 frame_type = *stackmap_p; + u1 frame_type = *stackmap_p; stackmap_p++; // same_frame { // u1 frame_type = SAME; /* 0-63 */ // } - if (frame_type >= 0 && frame_type <= 63) { + if (frame_type <= 63) { // nothing more to do for same_frame } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -364,10 +364,6 @@ os::release_memory((char *)(uintptr_t)addr, size); WB_END -WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env)) - return MemTracker::tracking_level() == NMT_detail; -WB_END - WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env)) // Test that we can downgrade NMT levels but not upgrade them. if (MemTracker::tracking_level() == NMT_off) { @@ -1321,7 +1317,6 @@ {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, - {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported}, {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel}, {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize }, #endif // INCLUDE_NMT diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/frame.hpp --- a/hotspot/src/share/vm/runtime/frame.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/frame.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -194,7 +194,6 @@ public: // Link (i.e., the pointer to the previous frame) intptr_t* link() const; - void set_link(intptr_t* addr); // Return address address sender_pc() const; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -921,6 +921,9 @@ "If > 0, provokes an error inside VM error handler (a secondary " \ "crash). see test_error_handler() in debug.cpp.") \ \ + notproduct(bool, TestSafeFetchInErrorHandler, false, \ + "If true, tests SafeFetch inside error handler.") \ + \ develop(bool, Verbose, false, \ "Print additional debugging information from other modes") \ \ diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/stubRoutines.cpp --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -210,8 +210,36 @@ assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything"); } } + +// simple test for SafeFetch32 +static void test_safefetch32() { + int dummy = 17; + int* const p_invalid = (int*) get_segfault_address(); + int* const p_valid = &dummy; + int result_invalid = SafeFetch32(p_invalid, 0xABC); + assert(result_invalid == 0xABC, "SafeFetch32 error"); + int result_valid = SafeFetch32(p_valid, 0xABC); + assert(result_valid == 17, "SafeFetch32 error"); +} + +// simple test for SafeFetchN +static void test_safefetchN() { +#ifdef _LP64 + const intptr_t v1 = UCONST64(0xABCD00000000ABCD); + const intptr_t v2 = UCONST64(0xDEFD00000000DEFD); +#else + const intptr_t v1 = 0xABCDABCD; + const intptr_t v2 = 0xDEFDDEFD; #endif - + intptr_t dummy = v1; + intptr_t* const p_invalid = (intptr_t*) get_segfault_address(); + intptr_t* const p_valid = &dummy; + intptr_t result_invalid = SafeFetchN(p_invalid, v2); + assert(result_invalid == v2, "SafeFetchN error"); + intptr_t result_valid = SafeFetchN(p_valid, v2); + assert(result_valid == v1, "SafeFetchN error"); +} +#endif void StubRoutines::initialize2() { if (_code2 == NULL) { @@ -300,6 +328,13 @@ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong)); test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong)); + // test safefetch routines + // Not on Windows 32bit until 8074860 is fixed +#if ! (defined(_WIN32) && defined(_M_IX86)) + test_safefetch32(); + test_safefetchN(); +#endif + #endif } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -448,4 +448,9 @@ return StubRoutines::SafeFetchN_stub()(adr, errValue); } + +// returns true if SafeFetch32 and SafeFetchN can be used safely (stubroutines are already generated) +inline bool CanUseSafeFetch32() { return StubRoutines::SafeFetch32_stub() ? true : false; } +inline bool CanUseSafeFetchN() { return StubRoutines::SafeFetchN_stub() ? true : false; } + #endif // SHARE_VM_RUNTIME_STUBROUTINES_HPP diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -203,8 +203,6 @@ // This initial value ==> never claimed. _oops_do_parity = 0; - _metadata_on_stack_buffer = NULL; - // the handle mark links itself to last_handle_mark new HandleMark(this); @@ -776,7 +774,8 @@ // no nmethods in a generic thread... } -void Thread::metadata_do(void f(Metadata*)) { +void Thread::metadata_handles_do(void f(Metadata*)) { + // Only walk the Handles in Thread. if (metadata_handles() != NULL) { for (int i = 0; i< metadata_handles()->length(); i++) { f(metadata_handles()->at(i)); @@ -2713,7 +2712,6 @@ } void JavaThread::metadata_do(void f(Metadata*)) { - Thread::metadata_do(f); if (has_last_Java_frame()) { // Traverse the execution stack to call f() on the methods in the stack for (StackFrameStream fst(this); !fst.is_done(); fst.next()) { @@ -4104,6 +4102,21 @@ } } +class ThreadHandlesClosure : public ThreadClosure { + void (*_f)(Metadata*); + public: + ThreadHandlesClosure(void f(Metadata*)) : _f(f) {} + virtual void do_thread(Thread* thread) { + thread->metadata_handles_do(_f); + } +}; + +void Threads::metadata_handles_do(void f(Metadata*)) { + // Only walk the Handles in Thread. + ThreadHandlesClosure handles_closure(f); + threads_do(&handles_closure); +} + void Threads::deoptimized_wrt_marked_nmethods() { ALL_JAVA_THREADS(p) { p->deoptimized_wrt_marked_nmethods(); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/thread.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -255,9 +255,6 @@ jlong _allocated_bytes; // Cumulative number of bytes allocated on // the Java heap - // Thread-local buffer used by MetadataOnStackMark. - MetadataOnStackBuffer* _metadata_on_stack_buffer; - TRACE_DATA _trace_data; // Thread-local data for tracing ThreadExt _ext; @@ -478,7 +475,7 @@ void nmethods_do(CodeBlobClosure* cf); // jvmtiRedefineClasses support - void metadata_do(void f(Metadata*)); + void metadata_handles_do(void f(Metadata*)); // Used by fast lock support virtual bool is_lock_owned(address adr) const; @@ -494,9 +491,6 @@ // creation fails due to lack of memory, too many threads etc. bool set_as_starting_thread(); - void set_metadata_on_stack_buffer(MetadataOnStackBuffer* buffer) { _metadata_on_stack_buffer = buffer; } - MetadataOnStackBuffer* metadata_on_stack_buffer() const { return _metadata_on_stack_buffer; } - protected: // OS data associated with the thread OSThread* _osthread; // Platform-specific thread information @@ -1915,6 +1909,7 @@ // RedefineClasses support static void metadata_do(void f(Metadata*)); + static void metadata_handles_do(void f(Metadata*)); #ifdef ASSERT static bool is_vm_complete() { return _vm_complete; } diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/virtualspace.cpp --- a/hotspot/src/share/vm/runtime/virtualspace.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -519,12 +519,13 @@ // Calc address range within we try to attach (range of possible start addresses). char *const highest_start = (char *)align_ptr_down(zerobased_max - size, attach_point_alignment); - // SS10 and SS12u1 cannot compile "(char *)UnscaledOopHeapMax - size" on solaris sparc 32-bit: - // "Cannot use int to initialize char*." Introduce aux variable. - char *unscaled_end = (char *)UnscaledOopHeapMax; - unscaled_end -= size; - char *lowest_start = (size < UnscaledOopHeapMax) ? - MAX2(unscaled_end, aligned_heap_base_min_address) : aligned_heap_base_min_address; + // Need to be careful about size being guaranteed to be less + // than UnscaledOopHeapMax due to type constraints. + char *lowest_start = aligned_heap_base_min_address; + uint64_t unscaled_end = UnscaledOopHeapMax - size; + if (unscaled_end < UnscaledOopHeapMax) { // unscaled_end wrapped if size is large + lowest_start = MAX2(lowest_start, (char*)unscaled_end); + } lowest_start = (char *)align_ptr_up(lowest_start, attach_point_alignment); try_reserve_range(highest_start, lowest_start, attach_point_alignment, aligned_heap_base_min_address, zerobased_max, size, alignment, large); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -2584,7 +2584,6 @@ /**********************/ \ /* frame */ \ /**********************/ \ - NOT_ZERO(PPC64_ONLY(declare_constant(frame::abi_minframe_size))) \ NOT_ZERO(PPC64_ONLY(declare_constant(frame::entry_frame_locals_size))) \ \ NOT_ZERO(X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset))) \ diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/services/memTracker.cpp --- a/hotspot/src/share/vm/services/memTracker.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/services/memTracker.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -53,11 +53,7 @@ if (strcmp(nmt_option, "summary") == 0) { level = NMT_summary; } else if (strcmp(nmt_option, "detail") == 0) { -#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED level = NMT_detail; -#else - level = NMT_summary; -#endif // PLATFORM_NATIVE_STACK_WALKING_SUPPORTED } else if (strcmp(nmt_option, "off") != 0) { // The option value is invalid _is_nmt_env_valid = false; @@ -95,17 +91,9 @@ bool MemTracker::check_launcher_nmt_support(const char* value) { if (strcmp(value, "=detail") == 0) { -#if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED - jio_fprintf(defaultStream::error_stream(), - "NMT detail is not supported on this platform. Using NMT summary instead.\n"); - if (MemTracker::tracking_level() != NMT_summary) { - return false; - } -#else if (MemTracker::tracking_level() != NMT_detail) { return false; } -#endif } else if (strcmp(value, "=summary") == 0) { if (MemTracker::tracking_level() != NMT_summary) { return false; diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/trace/trace.xml --- a/hotspot/src/share/vm/trace/trace.xml Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/trace/trace.xml Mon Apr 06 10:35:43 2015 -0700 @@ -400,6 +400,22 @@ + + + + + + + + + + + + + + + = 0, "just checking"); } @@ -45,7 +44,6 @@ } void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { - assert(size_in_bits >= 0, "just checking"); idx_t old_size_in_words = size_in_words(); bm_word_t* old_map = map(); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -446,15 +446,6 @@ # include "globalDefinitions_aarch64.hpp" #endif -/* - * If a platform does not support native stack walking - * the platform specific globalDefinitions (above) - * can set PLATFORM_NATIVE_STACK_WALKING_SUPPORTED to 0 - */ -#ifndef PLATFORM_NATIVE_STACK_WALKING_SUPPORTED -#define PLATFORM_NATIVE_STACK_WALKING_SUPPORTED 1 -#endif - // To assure the IRIW property on processors that are not multiple copy // atomic, sync instructions must be issued between volatile reads to // assure their ordering, instead of after volatile stores. diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -44,14 +44,6 @@ #endif // SOLARIS #include -#ifndef FP_PZERO -// Linux doesn't have positive/negative zero -#define FP_PZERO FP_ZERO -#endif -#if (!defined fpclass) && ((!defined SPARC) || (!defined SOLARIS)) -#define fpclass fpclassify -#endif - #include #include #include diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -48,15 +48,6 @@ # include #endif # include -#ifdef LINUX -#ifndef FP_PZERO - // Linux doesn't have positive/negative zero - #define FP_PZERO FP_ZERO -#endif -#ifndef fpclass - #define fpclass fpclassify -#endif -#endif # include # include # include diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Mon Apr 06 10:35:43 2015 -0700 @@ -41,14 +41,6 @@ #include #include -#ifndef FP_PZERO -// Linux doesn't have positive/negative zero -#define FP_PZERO FP_ZERO -#endif -#if (!defined fpclass) -#define fpclass fpclassify -#endif - #include #include #include diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/nativeCallStack.cpp --- a/hotspot/src/share/vm/utilities/nativeCallStack.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -32,10 +32,6 @@ NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : _hash_value(0) { -#if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED - fillStack = false; -#endif - if (fillStack) { os::get_native_stack(_stack, NMT_TrackingStackDepth, toSkip); } else { @@ -95,11 +91,7 @@ int offset; if (is_empty()) { for (int index = 0; index < indent; index ++) out->print(" "); -#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED out->print("[BOOTSTRAP]"); -#else - out->print("[No stack]"); -#endif } else { for (int frame = 0; frame < NMT_TrackingStackDepth; frame ++) { pc = get_frame(frame); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/vmError.cpp --- a/hotspot/src/share/vm/utilities/vmError.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -358,18 +358,38 @@ // test secondary error handling. Test it twice, to test that resetting // error handler after a secondary crash works. - STEP(13, "(test secondary crash 1)") + STEP(11, "(test secondary crash 1)") + if (_verbose && TestCrashInErrorHandler != 0) { + st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...", + TestCrashInErrorHandler); + controlled_crash(TestCrashInErrorHandler); + } + + STEP(12, "(test secondary crash 2)") if (_verbose && TestCrashInErrorHandler != 0) { st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...", TestCrashInErrorHandler); controlled_crash(TestCrashInErrorHandler); } - STEP(14, "(test secondary crash 2)") - if (_verbose && TestCrashInErrorHandler != 0) { - st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...", - TestCrashInErrorHandler); - controlled_crash(TestCrashInErrorHandler); + STEP(13, "(test safefetch in error handler)") + // test whether it is safe to use SafeFetch32 in Crash Handler. Test twice + // to test that resetting the signal handler works correctly. + if (_verbose && TestSafeFetchInErrorHandler) { + st->print_cr("Will test SafeFetch..."); + if (CanUseSafeFetch32()) { + int* const invalid_pointer = (int*) get_segfault_address(); + const int x = 0x76543210; + int i1 = SafeFetch32(invalid_pointer, x); + int i2 = SafeFetch32(invalid_pointer, x); + if (i1 == x && i2 == x) { + st->print_cr("SafeFetch OK."); // Correctly deflected and returned default pattern + } else { + st->print_cr("??"); + } + } else { + st->print_cr("not possible; skipped."); + } } #endif // PRODUCT diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/workgroup.cpp --- a/hotspot/src/share/vm/utilities/workgroup.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/workgroup.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -124,7 +124,7 @@ // Array index bounds checking. GangWorker* result = NULL; assert(gang_workers() != NULL, "No workers for indexing"); - assert(((i >= 0) && (i < total_workers())), "Worker index out of bounds"); + assert(i < total_workers(), "Worker index out of bounds"); result = _gang_workers[i]; assert(result != NULL, "Indexing to null worker"); return result; @@ -463,7 +463,7 @@ } bool SubTasksDone::is_task_claimed(uint t) { - assert(0 <= t && t < _n_tasks, "bad task id."); + assert(t < _n_tasks, "bad task id."); uint old = _tasks[t]; if (old == 0) { old = Atomic::cmpxchg(1, &_tasks[t], 0); diff -r d47c58140b41 -r 427f83353f73 hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp --- a/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, 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 @@ -120,7 +120,6 @@ _sequence_number++; uint requested_size = new_task->requested_size(); - assert(requested_size >= 0, "Should be non-negative"); if (requested_size != 0) { _active_workers = MIN2(requested_size, total_workers()); } else { diff -r d47c58140b41 -r 427f83353f73 hotspot/test/compiler/loopopts/ConstFPVectorization.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/loopopts/ConstFPVectorization.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8074869 + * @summary C2 code generator can replace -0.0f with +0.0f on Linux + * @run main ConstFPVectorization 8 + * @author volker.simonis@gmail.com + * + */ + +public class ConstFPVectorization { + + static float[] f = new float[16]; + static double[] d = new double[16]; + + static void floatLoop(int count) { + for (int i = 0; i < count; i++) { + f[i] = -0.0f; + } + } + + static void doubleLoop(int count) { + for (int i = 0; i < count; i++) { + d[i] = -0.0d; + } + } + + public static void main(String args[]) { + for (int i = 0; i < 10_000; i++) { + floatLoop(Integer.parseInt(args[0])); + doubleLoop(Integer.parseInt(args[0])); + } + for (int i = 0; i < Integer.parseInt(args[0]); i++) { + if (Float.floatToRawIntBits(f[i]) != Float.floatToRawIntBits(-0.0f)) + throw new Error("Float error at index " + i); + if (Double.doubleToRawLongBits(d[i]) != Double.doubleToRawLongBits(-0.0d)) + throw new Error("Double error at index " + i); + } + } +} diff -r d47c58140b41 -r 427f83353f73 hotspot/test/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,92 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.regex.Pattern; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.ProcessTools; + +/* + * @test + * @bug 8074552 + * @summary SafeFetch32 and SafeFetchN do not work in error handling + * @library /testlibrary + * @author Thomas Stuefe (SAP) + */ + +public class SafeFetchInErrorHandlingTest { + + + public static void main(String[] args) throws Exception { + + if (!Platform.isDebugBuild()) { + return; + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-Xmx100M", + "-XX:ErrorHandlerTest=14", + "-XX:+TestSafeFetchInErrorHandler", + "-version"); + + OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); + + // we should have crashed with a SIGSEGV + output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*"); + output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*"); + + // extract hs-err file + String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); + if (hs_err_file == null) { + throw new RuntimeException("Did not find hs-err file in output.\n"); + } + + File f = new File(hs_err_file); + if (!f.exists()) { + throw new RuntimeException("hs-err file missing at " + + f.getAbsolutePath() + ".\n"); + } + + System.out.println("Found hs_err file. Scanning..."); + + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line = null; + + Pattern [] pattern = new Pattern[] { + Pattern.compile("Will test SafeFetch..."), + Pattern.compile("SafeFetch OK."), + }; + int currentPattern = 0; + + String lastLine = null; + while ((line = br.readLine()) != null) { + if (currentPattern < pattern.length) { + if (pattern[currentPattern].matcher(line).matches()) { + System.out.println("Found: " + line + "."); + currentPattern ++; + } + } + lastLine = line; + } + br.close(); + + if (currentPattern < pattern.length) { + throw new RuntimeException("hs-err file incomplete (first missing pattern: " + currentPattern + ")"); + } + + if (!lastLine.equals("END.")) { + throw new RuntimeException("hs-err file incomplete (missing END marker.)"); + } else { + System.out.println("End marker found."); + } + + System.out.println("OK."); + + } + +} + diff -r d47c58140b41 -r 427f83353f73 hotspot/test/runtime/NMT/ChangeTrackingLevel.java --- a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -27,7 +27,6 @@ * @summary Test that you can decrease NMT tracking level but not increase it. * @key nmt * @library /testlibrary /../../test/lib - * @ignore 8067167 * @build ChangeTrackingLevel * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff -r d47c58140b41 -r 427f83353f73 hotspot/test/runtime/NMT/PrintNMTStatistics.java --- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -27,7 +27,6 @@ * @bug 8005936 8058606 * @summary Verify PrintNMTStatistics on normal JVM exit for detail and summary tracking level * @library /testlibrary - * @ignore 8067167 */ import com.oracle.java.testlibrary.*; diff -r d47c58140b41 -r 427f83353f73 hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java --- a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -46,13 +46,6 @@ String pid = Integer.toString(ProcessTools.getProcessId()); ProcessBuilder pb = new ProcessBuilder(); - boolean has_nmt_detail = wb.NMTIsDetailSupported(); - if (has_nmt_detail) { - System.out.println("NMT detail support detected."); - } else { - System.out.println("NMT detail support not detected."); - } - Thread reserveThread = new Thread() { public void run() { addr = wb.NMTReserveMemory(reserveSize); @@ -64,9 +57,7 @@ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=512KB, committed=0KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test"); Thread commitThread = new Thread() { public void run() { @@ -78,9 +69,7 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=512KB, committed=128KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); Thread uncommitThread = new Thread() { public void run() { @@ -107,4 +96,4 @@ output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); } - } +} diff -r d47c58140b41 -r 427f83353f73 hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java --- a/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -49,13 +49,6 @@ String pid = Integer.toString(ProcessTools.getProcessId()); ProcessBuilder pb = new ProcessBuilder(); - boolean has_nmt_detail = wb.NMTIsDetailSupported(); - if (has_nmt_detail) { - System.out.println("NMT detail support detected."); - } else { - System.out.println("NMT detail support not detected."); - } - // reserve addr = wb.NMTReserveMemory(reserveSize); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, @@ -63,11 +56,9 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=0KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); long addrA = addr; long addrB = addr + commitSize; @@ -85,11 +76,9 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=512KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); // uncommit BC wb.NMTUncommitMemory(addrB, commitSize); wb.NMTUncommitMemory(addrC, commitSize); @@ -97,11 +86,9 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=256KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); // commit EF wb.NMTCommitMemory(addrE, commitSize); @@ -109,22 +96,18 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=512KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); // uncommit A wb.NMTUncommitMemory(addrA, commitSize); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=384KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); // commit ABC wb.NMTCommitMemory(addrA, commitSize); @@ -133,11 +116,9 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=768KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); // uncommit ABCDEF wb.NMTUncommitMemory(addrA, commitSize); @@ -149,11 +130,9 @@ output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=4096KB, committed=0KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" - + Long.toHexString(addr + reserveSize) - + "\\] reserved 4096KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 4096KB for Test"); // release wb.NMTReleaseMemory(addr, reserveSize); diff -r d47c58140b41 -r 427f83353f73 hotspot/test/runtime/NMT/VirtualAllocTestType.java --- a/hotspot/test/runtime/NMT/VirtualAllocTestType.java Tue Mar 31 16:22:59 2015 -0700 +++ b/hotspot/test/runtime/NMT/VirtualAllocTestType.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -47,30 +47,19 @@ String pid = Integer.toString(ProcessTools.getProcessId()); ProcessBuilder pb = new ProcessBuilder(); - boolean has_nmt_detail = wb.NMTIsDetailSupported(); - if (has_nmt_detail) { - System.out.println("NMT detail support detected."); - } else { - System.out.println("NMT detail support not detected."); - } - addr = wb.NMTReserveMemory(reserveSize); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=256KB, committed=0KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test"); wb.NMTCommitMemory(addr, commitSize); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=256KB, committed=128KB)"); - if (has_nmt_detail) { - output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); - } + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); wb.NMTUncommitMemory(addr, commitSize); @@ -85,4 +74,4 @@ output.shouldNotContain("Test (reserved="); output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); } - } +} diff -r d47c58140b41 -r 427f83353f73 jaxp/.hgtags --- a/jaxp/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/jaxp/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -298,3 +298,5 @@ d5b5a010a16688f188f5a9247ed873f5100b530c jdk9-b53 542c0c855ad467624cbedf11bff08e44b86b068d jdk9-b54 2a460ce60ed47081f756f0cc0321d8e9ba7cac17 jdk9-b55 +139092a10dedd32bc1155e40c67a6ef682e39873 jdk9-b56 +2c417f7d7b0dc98e887474884aa39f974894f0c2 jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 jaxp/test/Makefile --- a/jaxp/test/Makefile Tue Mar 31 16:22:59 2015 -0700 +++ b/jaxp/test/Makefile Mon Apr 06 10:35:43 2015 -0700 @@ -262,8 +262,8 @@ EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY) endif -# Default JTREG to run (win32 script works for everybody) -JTREG = $(JT_HOME)/win32/bin/jtreg +# Default JTREG to run +JTREG = $(JT_HOME)/bin/jtreg # run in agentvm mode JTREG_BASIC_OPTIONS += -agentvm # Only run automatic tests diff -r d47c58140b41 -r 427f83353f73 jaxws/.hgtags --- a/jaxws/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/jaxws/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -301,3 +301,5 @@ b8fbe40efa97fe0753076ccc6dfc50747c7877d0 jdk9-b53 83a0cf0e08788c33872e1fe3e87bf9a0d1e59eaa jdk9-b54 ca481b0492c82cc38fa0e6b746305ed88c26b4fd jdk9-b55 +b4f913b48e699980bd11fe19cce134d0adb4c31c jdk9-b56 +17c4241395e97312bd75e7acd693ffcdd41ae993 jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 jdk/.hgtags --- a/jdk/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -298,3 +298,5 @@ 6cb5f5c34009630749a40cefe116d143f0b2583e jdk9-b53 568a62ab7d764d7c74ac1d87387dbe500662b551 jdk9-b54 d49e247dade61f29f771f09b2105857492241156 jdk9-b55 +7969f7b6465e47ce4afa77670ca600b04c1d746c jdk9-b56 +c76339e86ea7da5d9ac7856f3fae9ef73eef04a2 jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 jdk/make/launcher/Launcher-jdk.pack200.gmk --- a/jdk/make/launcher/Launcher-jdk.pack200.gmk Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk Mon Apr 06 10:35:43 2015 -0700 @@ -79,9 +79,6 @@ CFLAGS_linux := -fPIC, \ CFLAGS_solaris := -KPIC, \ CFLAGS_macosx := -fPIC, \ - DISABLED_WARNINGS_gcc := sign-compare unused-result format-nonliteral \ - format-security parentheses, \ - DISABLED_WARNINGS_microsoft := 4267 4018, \ MAPFILE := $(UNPACK_MAPFILE),\ LDFLAGS := $(UNPACKEXE_ZIPOBJS) \ $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ diff -r d47c58140b41 -r 427f83353f73 jdk/make/lib/Lib-jdk.pack200.gmk --- a/jdk/make/lib/Lib-jdk.pack200.gmk Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/make/lib/Lib-jdk.pack200.gmk Mon Apr 06 10:35:43 2015 -0700 @@ -40,11 +40,6 @@ -I$(JDK_TOPDIR)/src/jdk.pack200/share/native/common-unpack \ $(LIBJAVA_HEADER_FLAGS), \ CFLAGS_release := -DPRODUCT, \ - DISABLED_WARNINGS_gcc := conversion-null sign-compare format-security \ - format-nonliteral parentheses, \ - DISABLED_WARNINGS_clang := bool-conversion format-security, \ - DISABLED_WARNINGS_solstudio := truncwarn, \ - DISABLED_WARNINGS_microsoft := 4267 4018, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libunpack/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,10 @@ import java.net.URL; import java.net.HttpURLConnection; import java.io.IOException; +import java.security.cert.Certificate; import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; - -import javax.security.cert.X509Certificate; +import javax.net.ssl.SSLPeerUnverifiedException; /** * HTTP URL connection with support for HTTPS-specific features. See @@ -70,7 +70,8 @@ * the server did not authenticate. * @return the server certificate chain */ - public abstract X509Certificate [] getServerCertificateChain(); + public abstract Certificate[] getServerCertificates() + throws SSLPeerUnverifiedException; /** * HostnameVerifier provides a callback mechanism so that diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,25 +187,6 @@ return delegate.getServerCertificates(); } - /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * NOTE: This method is not necessary for the version of this class - * implementing javax.net.ssl.HttpsURLConnection, but provided for - * compatibility with the com.sun.net.ssl.HttpsURLConnection version. - */ - public javax.security.cert.X509Certificate[] getServerCertificateChain() { - try { - return delegate.getServerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - // this method does not throw an exception as declared in - // com.sun.net.ssl.HttpsURLConnection. - // Return null for compatibility. - return null; - } - } - /* * Allowable input/output sequences: * [interpreted as POST/PUT] diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Mon Apr 06 10:35:43 2015 -0700 @@ -82,7 +82,7 @@ *
  • a destination for standard output * and standard error. By default, the subprocess writes standard * output and standard error to pipes. Java code can access these pipes - * via the input streams returned by {@link Process#getInputStream()} and + * via the input streams returned by {@link Process#getOutputStream()} and * {@link Process#getErrorStream()}. However, standard output and * standard error may be redirected to other destinations using * {@link #redirectOutput(Redirect) redirectOutput} and @@ -988,14 +988,14 @@ *
  • the standard input to the subprocess was * {@linkplain #redirectInput redirected from a file} * and the security manager's - * {@link SecurityManager#checkRead checkRead} method + * {@link SecurityManager#checkRead(String) checkRead} method * denies read access to the file, or * *
  • the standard output or standard error of the * subprocess was * {@linkplain #redirectOutput redirected to a file} * and the security manager's - * {@link SecurityManager#checkWrite checkWrite} method + * {@link SecurityManager#checkWrite(String) checkWrite} method * denies write access to the file * * diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/Date.java --- a/jdk/src/java.base/share/classes/java/util/Date.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/Date.java Mon Apr 06 10:35:43 2015 -0700 @@ -1317,6 +1317,7 @@ private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); s.writeLong(getTimeImpl()); } @@ -1326,6 +1327,7 @@ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); fastTime = s.readLong(); } diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/Optional.java --- a/jdk/src/java.base/share/classes/java/util/Optional.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/Optional.java Mon Apr 06 10:35:43 2015 -0700 @@ -346,7 +346,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/OptionalDouble.java --- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Mon Apr 06 10:35:43 2015 -0700 @@ -244,7 +244,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/OptionalInt.java --- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java Mon Apr 06 10:35:43 2015 -0700 @@ -244,7 +244,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/OptionalLong.java --- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java Mon Apr 06 10:35:43 2015 -0700 @@ -244,7 +244,7 @@ * * * @param obj an object to be tested for equality - * @return {code true} if the other object is "equal to" this object + * @return {@code true} if the other object is "equal to" this object * otherwise {@code false} */ @Override diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/Properties.java --- a/jdk/src/java.base/share/classes/java/util/Properties.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/Properties.java Mon Apr 06 10:35:43 2015 -0700 @@ -309,7 +309,7 @@ * input stream. * @throws IllegalArgumentException if a malformed Unicode escape * appears in the input. - * @throws NullPointerException if {@code reader} is null. + * @throws NullPointerException if {@code reader} is null. * @since 1.6 */ public synchronized void load(Reader reader) throws IOException { @@ -335,7 +335,7 @@ * input stream. * @throws IllegalArgumentException if the input stream contains a * malformed Unicode escape sequence. - * @throws NullPointerException if {@code inStream} is null. + * @throws NullPointerException if {@code inStream} is null. * @since 1.2 */ public synchronized void load(InputStream inStream) throws IOException { diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java --- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -380,60 +380,6 @@ } /** - * Prepare the pipeline for a parallel execution. As the pipeline is built, - * the flags and depth indicators are set up for a sequential execution. - * If the execution is parallel, and there are any stateful operations, then - * some of these need to be adjusted, as well as adjusting for flags from - * the terminal operation (such as back-propagating UNORDERED). - * Need not be called for a sequential execution. - * - * @param terminalFlags Operation flags for the terminal operation - */ - private void parallelPrepare(int terminalFlags) { - @SuppressWarnings("rawtypes") - AbstractPipeline backPropagationHead = sourceStage; - if (sourceStage.sourceAnyStateful) { - int depth = 1; - for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage; - p != null; - u = p, p = p.nextStage) { - int thisOpFlags = p.sourceOrOpFlags; - if (p.opIsStateful()) { - // If the stateful operation is a short-circuit operation - // then move the back propagation head forwards - // NOTE: there are no size-injecting ops - if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) { - backPropagationHead = p; - // Clear the short circuit flag for next pipeline stage - // This stage encapsulates short-circuiting, the next - // stage may not have any short-circuit operations, and - // if so spliterator.forEachRemaining should be used - // for traversal - thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT; - } - - depth = 0; - // The following injects size, it is equivalent to: - // StreamOpFlag.combineOpFlags(StreamOpFlag.IS_SIZED, p.combinedFlags); - thisOpFlags = (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED; - } - p.depth = depth++; - p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags); - } - } - - // Apply the upstream terminal flags - if (terminalFlags != 0) { - int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; - for ( @SuppressWarnings("rawtypes") AbstractPipeline p = backPropagationHead; p.nextStage != null; p = p.nextStage) { - p.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, p.combinedFlags); - } - - combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags); - } - } - - /** * Get the source spliterator for this pipeline stage. For a sequential or * stateless parallel pipeline, this is the source spliterator. For a * stateful parallel pipeline, this is a spliterator describing the results @@ -456,24 +402,70 @@ throw new IllegalStateException(MSG_CONSUMED); } - if (isParallel()) { - // @@@ Merge parallelPrepare with the loop below and use the - // spliterator characteristics to determine if SIZED - // should be injected - parallelPrepare(terminalFlags); + boolean hasTerminalFlags = terminalFlags != 0; + if (isParallel() && sourceStage.sourceAnyStateful) { + // Adjust pipeline stages if there are stateful ops, + // and find the last short circuiting op, if any, that + // defines the head stage for back-propagation of terminal flags + @SuppressWarnings("rawtypes") + AbstractPipeline backPropagationHead = sourceStage; + int depth = 1; + for (@SuppressWarnings("rawtypes") AbstractPipeline p = sourceStage.nextStage; + p != null; + p = p.nextStage) { + if (p.opIsStateful()) { + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(p.sourceOrOpFlags)) { + // If the stateful operation is a short-circuit operation + // then move the back propagation head forwards + // NOTE: there are no size-injecting ops + backPropagationHead = p; + } + + depth = 0; + } + p.depth = depth++; + } // Adapt the source spliterator, evaluating each stateful op // in the pipeline up to and including this pipeline stage - for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; + // Flags for each pipeline stage are adjusted accordingly + boolean backPropagate = false; + int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; + for (@SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; u != e; u = p, p = p.nextStage) { + if (hasTerminalFlags && + (backPropagate || (backPropagate = (u == backPropagationHead)))) { + // Back-propagate flags from the terminal operation + u.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, u.combinedFlags); + } + + int thisOpFlags = p.sourceOrOpFlags; if (p.opIsStateful()) { + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) { + // Clear the short circuit flag for next pipeline stage + // This stage encapsulates short-circuiting, the next + // stage may not have any short-circuit operations, and + // if so spliterator.forEachRemaining should be used + // for traversal + thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT; + } + spliterator = p.opEvaluateParallelLazy(u, spliterator); + + // Inject or clear SIZED on the source pipeline stage + // based on the stage's spliterator + thisOpFlags = spliterator.hasCharacteristics(Spliterator.SIZED) + ? (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED + : (thisOpFlags & ~StreamOpFlag.IS_SIZED) | StreamOpFlag.NOT_SIZED; } + p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags); } } - else if (terminalFlags != 0) { + + if (hasTerminalFlags) { + // Apply flags from the terminal operation to last pipeline stage combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags); } diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java --- a/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/java/util/stream/ReduceOps.java Mon Apr 06 10:35:43 2015 -0700 @@ -264,6 +264,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -433,6 +438,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -602,6 +612,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } @@ -771,6 +786,11 @@ return spliterator.getExactSizeIfKnown(); return super.evaluateParallel(helper, spliterator); } + + @Override + public int getOpFlags() { + return StreamOpFlag.NOT_ORDERED; + } }; } diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java Mon Apr 06 10:35:43 2015 -0700 @@ -262,27 +262,6 @@ } /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - public javax.security.cert.X509Certificate[] getServerCertificateChain() - throws SSLPeerUnverifiedException { - if (cachedResponse != null) { - throw new UnsupportedOperationException("this method is not supported when using cache"); - } - if (http == null) { - throw new IllegalStateException("connection not yet open"); - } else { - return ((HttpsClient)http).getServerCertificateChain(); - } - } - - /** * Returns the server's principal, or throws SSLPeerUnverifiedException * if the server did not authenticate. */ diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Mon Apr 06 10:35:43 2015 -0700 @@ -697,21 +697,6 @@ } /** - * Returns the X.509 certificate chain with which the server - * authenticated itself, or null if the server did not authenticate. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - javax.security.cert.X509Certificate [] getServerCertificateChain() - throws SSLPeerUnverifiedException - { - return session.getPeerCertificateChain(); - } - - /** * Returns the principal with which the server authenticated * itself, or throw a SSLPeerUnverifiedException if the * server did not authenticate. diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Mon Apr 06 10:35:43 2015 -0700 @@ -198,30 +198,6 @@ } /** - * Returns the server's X.509 certificate chain, or null if - * the server did not authenticate. - * - * NOTE: This method is not necessary for the version of this class - * implementing javax.net.ssl.HttpsURLConnection, but provided for - * compatibility with the com.sun.net.ssl.HttpsURLConnection version. - * - * @deprecated This method returns the deprecated - * {@code javax.security.cert.X509Certificate} type. - * Use {@code getServerCertificates()} instead. - */ - @Deprecated - public javax.security.cert.X509Certificate[] getServerCertificateChain() { - try { - return delegate.getServerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - // this method does not throw an exception as declared in - // com.sun.net.ssl.HttpsURLConnection. - // Return null for compatibility. - return null; - } - } - - /** * Returns the principal with which the server authenticated itself, * or throw a SSLPeerUnverifiedException if the server did not authenticate. */ diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java --- a/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Mon Apr 06 10:35:43 2015 -0700 @@ -290,8 +290,9 @@ throw new SignatureException("Cert request was not signed"); + byte[] CRLF = new byte[] {'\r', '\n'}; out.println("-----BEGIN NEW CERTIFICATE REQUEST-----"); - out.println(Base64.getMimeEncoder().encodeToString(encoded)); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(encoded)); out.println("-----END NEW CERTIFICATE REQUEST-----"); } diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java --- a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java Mon Apr 06 10:35:43 2015 -0700 @@ -28,6 +28,8 @@ import java.io.*; import java.util.*; import java.security.cert.*; + +import sun.security.util.Pem; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.pkcs.PKCS7; @@ -633,7 +635,7 @@ checkHeaderFooter(header.toString(), footer.toString()); - return Base64.getMimeDecoder().decode(new String(data, 0, pos)); + return Pem.decode(new String(data, 0, pos)); } } diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Mon Apr 06 10:35:43 2015 -0700 @@ -80,6 +80,7 @@ import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; import sun.security.util.DerValue; +import sun.security.util.Pem; import sun.security.x509.*; import static java.security.KeyStore.*; @@ -100,6 +101,8 @@ */ public final class Main { + private static final byte[] CRLF = new byte[] {'\r', '\n'}; + private boolean debug = false; private Command command = null; private String sigAlgName = null; @@ -1266,7 +1269,7 @@ sb.append(s); } } - byte[] rawReq = Base64.getMimeDecoder().decode(new String(sb)); + byte[] rawReq = Pem.decode(new String(sb)); PKCS10 req = new PKCS10(rawReq); info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo())); @@ -1343,7 +1346,7 @@ crl.sign(privateKey, sigAlgName); if (rfc) { out.println("-----BEGIN X509 CRL-----"); - out.println(Base64.getMimeEncoder().encodeToString(crl.getEncodedInternal())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal())); out.println("-----END X509 CRL-----"); } else { out.write(crl.getEncodedInternal()); @@ -2304,7 +2307,7 @@ if (rfc) { X509CRL xcrl = (X509CRL)crl; out.println("-----BEGIN X509 CRL-----"); - out.println(Base64.getMimeEncoder().encodeToString(xcrl.getEncoded())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded())); out.println("-----END X509 CRL-----"); } else { out.println(crl.toString()); @@ -2331,7 +2334,7 @@ sb.append(s); } } - PKCS10 req = new PKCS10(Base64.getMimeDecoder().decode(new String(sb))); + PKCS10 req = new PKCS10(Pem.decode(new String(sb))); PublicKey pkey = req.getSubjectPublicKeyInfo(); out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."), @@ -3115,7 +3118,7 @@ { if (rfc) { out.println(X509Factory.BEGIN_CERT); - out.println(Base64.getMimeEncoder().encodeToString(cert.getEncoded())); + out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(cert.getEncoded())); out.println(X509Factory.END_CERT); } else { out.write(cert.getEncoded()); // binary diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/security/util/Pem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/util/Pem.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.io.IOException; +import java.util.Base64; + +/** + * The Length interface defines the length of an object + */ +public class Pem { + + /** + * Decodes a PEM-encoded block. + * + * @param input the input string, according to RFC 1421, can only contain + * characters in the base-64 alphabet and whitespaces. + * @return the decoded bytes + * @throws java.io.IOException if input is invalid + */ + public static byte[] decode(String input) throws IOException { + byte[] src = input.replaceAll("\\s+", "").getBytes(); + try { + return Base64.getDecoder().decode(src); + } catch (IllegalArgumentException e) { + throw new IOException(e); + } + } +} diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java --- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Mon Apr 06 10:35:43 2015 -0700 @@ -271,7 +271,7 @@ der = new DerValue(decstream.toByteArray()); break; } else { - decstream.write(Base64.getMimeDecoder().decode(line)); + decstream.write(Pem.decode(line)); } } } catch (IOException ioe2) { diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Mon Apr 06 10:35:43 2015 -0700 @@ -496,12 +496,11 @@ public synchronized boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (hasExited) return true; if (timeout <= 0) return false; - long remainingNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + remainingNanos; - do { // Round up to next millisecond wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L)); diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java --- a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Mon Apr 06 10:35:43 2015 -0700 @@ -458,12 +458,11 @@ public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; if (timeout <= 0) return false; - long remainingNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + remainingNanos ; - do { // Round up to next millisecond long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L); diff -r d47c58140b41 -r 427f83353f73 jdk/src/java.management/share/classes/com/sun/management/DiagnosticCommandMBean.java --- a/jdk/src/java.management/share/classes/com/sun/management/DiagnosticCommandMBean.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/java.management/share/classes/com/sun/management/DiagnosticCommandMBean.java Mon Apr 06 10:35:43 2015 -0700 @@ -31,7 +31,7 @@ /** * Management interface for the diagnostic commands for the HotSpot Virtual Machine. * - *

    The {code DiagnosticCommandMBean} is registered to the + *

    The {@code DiagnosticCommandMBean} is registered to the * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer * platform MBeanServer} as are other platform MBeans. * diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c --- a/jdk/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c Mon Apr 06 10:35:43 2015 -0700 @@ -26,6 +26,7 @@ #include "jni.h" #include "jni_util.h" +#include "jvm.h" #include #include @@ -184,15 +185,26 @@ res = errno; } - /* release p here before we throw an I/O exception */ - if (isCopy) { - JNU_ReleaseStringPlatformChars(env, path, p); - } - if (res == 0) { - if ( (sb.st_uid != uid) || (sb.st_gid != gid) || - ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) ) { - JNU_ThrowIOException(env, "well-known file is not secure"); + char msg[100]; + jboolean isError = JNI_FALSE; + if (sb.st_uid != uid) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; + } else if (sb.st_gid != gid) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) { + jio_snprintf(msg, sizeof(msg)-1, + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777); + isError = JNI_TRUE; + } + if (isError) { + char buf[256]; + jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg); + JNU_ThrowIOException(env, buf); } } else { char* msg = strdup(strerror(res)); @@ -201,6 +213,10 @@ free(msg); } } + + if (isCopy) { + JNU_ReleaseStringPlatformChars(env, path, p); + } } } diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c --- a/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c Mon Apr 06 10:35:43 2015 -0700 @@ -25,6 +25,7 @@ #include "jni.h" #include "jni_util.h" +#include "jvm.h" #include #include @@ -369,15 +370,26 @@ res = errno; } - /* release p here before we throw an I/O exception */ - if (isCopy) { - JNU_ReleaseStringPlatformChars(env, path, p); - } - if (res == 0) { - if ( (sb.st_uid != uid) || (sb.st_gid != gid) || - ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) ) { - JNU_ThrowIOException(env, "well-known file is not secure"); + char msg[100]; + jboolean isError = JNI_FALSE; + if (sb.st_uid != uid) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; + } else if (sb.st_gid != gid) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) { + jio_snprintf(msg, sizeof(msg)-1, + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777); + isError = JNI_TRUE; + } + if (isError) { + char buf[256]; + jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg); + JNU_ThrowIOException(env, buf); } } else { char* msg = strdup(strerror(res)); @@ -386,6 +398,10 @@ free(msg); } } + + if (isCopy) { + JNU_ReleaseStringPlatformChars(env, path, p); + } } } diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c --- a/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c Mon Apr 06 10:35:43 2015 -0700 @@ -25,6 +25,7 @@ #include "jni.h" #include "jni_util.h" +#include "jvm.h" #include #include @@ -151,15 +152,26 @@ res = errno; } - /* release p here before we throw an I/O exception */ - if (isCopy) { - JNU_ReleaseStringPlatformChars(env, path, p); - } - if (res == 0) { - if ( (sb.st_uid != uid) || (sb.st_gid != gid) || - ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) ) { - JNU_ThrowIOException(env, "well-known file is not secure"); + char msg[100]; + jboolean isError = JNI_FALSE; + if (sb.st_uid != uid) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; + } else if (sb.st_gid != gid) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) { + jio_snprintf(msg, sizeof(msg)-1, + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777); + isError = JNI_TRUE; + } + if (isError) { + char buf[256]; + jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg); + JNU_ThrowIOException(env, buf); } } else { char* msg = strdup(strerror(res)); @@ -168,6 +180,10 @@ free(msg); } } + + if (isCopy) { + JNU_ReleaseStringPlatformChars(env, path, p); + } } } diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c --- a/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c Mon Apr 06 10:35:43 2015 -0700 @@ -35,6 +35,7 @@ #include "jni.h" #include "jni_util.h" +#include "jvm.h" #include "sun_tools_attach_VirtualMachineImpl.h" @@ -112,15 +113,26 @@ res = errno; } - /* release p here before we throw an I/O exception */ - if (isCopy) { - JNU_ReleaseStringPlatformChars(env, path, p); - } - if (res == 0) { - if ( (sb.st_uid != uid) || (sb.st_gid != gid) || - ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) ) { - JNU_ThrowIOException(env, "well-known file is not secure"); + char msg[100]; + jboolean isError = JNI_FALSE; + if (sb.st_uid != uid) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; + } else if (sb.st_gid != gid) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) { + jio_snprintf(msg, sizeof(msg)-1, + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777); + isError = JNI_TRUE; + } + if (isError) { + char buf[256]; + jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg); + JNU_ThrowIOException(env, buf); } } else { char* msg = strdup(strerror(res)); @@ -129,6 +141,10 @@ free(msg); } } + + if (isCopy) { + JNU_ReleaseStringPlatformChars(env, path, p); + } } } diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,7 +142,7 @@ new String[] { "Jan", // abb january "Feb", // abb february - "Mrz", // abb march + "M\u00e4r", // abb march "Apr", // abb april "Mai", // abb may "Jun", // abb june diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/common-unpack/bytes.h --- a/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/bytes.h Mon Apr 06 10:35:43 2015 -0700 @@ -63,7 +63,7 @@ bytes res; res.ptr = ptr + beg; res.len = end - beg; - assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit()-1)); + assert(res.len == 0 || (inBounds(res.ptr) && inBounds(res.limit()-1))); return res; } // building C strings inside byte buffers: diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -225,9 +225,9 @@ } #ifdef PRODUCT - char* string() { return 0; } + const char* string() { return NULL; } #else - char* string(); // see far below + const char* string(); // see far below #endif }; @@ -718,13 +718,13 @@ // Now we can size the whole archive. // Read everything else into a mega-buffer. rp = hdr.rp; - int header_size_0 = (int)(rp - input.base()); // used-up header (4byte + 3int) - int header_size_1 = (int)(rplimit - rp); // buffered unused initial fragment - int header_size = header_size_0+header_size_1; + size_t header_size_0 = (rp - input.base()); // used-up header (4byte + 3int) + size_t header_size_1 = (rplimit - rp); // buffered unused initial fragment + size_t header_size = header_size_0 + header_size_1; unsized_bytes_read = header_size_0; CHECK; if (foreign_buf) { - if (archive_size > (size_t)header_size_1) { + if (archive_size > header_size_1) { abort("EOF reading fixed input buffer"); return; } @@ -738,7 +738,7 @@ return; } input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)), - (size_t) header_size_0 + archive_size); + header_size_0 + archive_size); CHECK; assert(input.limit()[0] == 0); // Move all the bytes we read initially into the real buffer. @@ -961,13 +961,13 @@ nentries = next_entry; // place a limit on future CP growth: - int generous = 0; + size_t generous = 0; generous = add_size(generous, u->ic_count); // implicit name generous = add_size(generous, u->ic_count); // outer generous = add_size(generous, u->ic_count); // outer.utf8 generous = add_size(generous, 40); // WKUs, misc generous = add_size(generous, u->class_count); // implicit SourceFile strings - maxentries = add_size(nentries, generous); + maxentries = (uint)add_size(nentries, generous); // Note that this CP does not include "empty" entries // for longs and doubles. Those are introduced when @@ -985,8 +985,9 @@ } // Initialize *all* our entries once - for (int i = 0 ; i < maxentries ; i++) + for (uint i = 0 ; i < maxentries ; i++) { entries[i].outputIndex = REQUESTED_NONE; + } initGroupIndexes(); // Initialize hashTab to a generous power-of-two size. @@ -3680,21 +3681,22 @@ unpacker* debug_u; -static bytes& getbuf(int len) { // for debugging only! +static bytes& getbuf(size_t len) { // for debugging only! static int bn = 0; static bytes bufs[8]; bytes& buf = bufs[bn++ & 7]; - while ((int)buf.len < len+10) + while (buf.len < len + 10) { buf.realloc(buf.len ? buf.len * 2 : 1000); + } buf.ptr[0] = 0; // for the sake of strcat return buf; } -char* entry::string() { +const char* entry::string() { bytes buf; switch (tag) { case CONSTANT_None: - return (char*)""; + return ""; case CONSTANT_Signature: if (value.b.ptr == null) return ref(0)->string(); @@ -3714,26 +3716,28 @@ break; default: if (nrefs == 0) { - buf = getbuf(20); - sprintf((char*)buf.ptr, TAG_NAME[tag]); + return TAG_NAME[tag]; } else if (nrefs == 1) { return refs[0]->string(); } else { - char* s1 = refs[0]->string(); - char* s2 = refs[1]->string(); - buf = getbuf((int)strlen(s1) + 1 + (int)strlen(s2) + 4 + 1); + const char* s1 = refs[0]->string(); + const char* s2 = refs[1]->string(); + buf = getbuf(strlen(s1) + 1 + strlen(s2) + 4 + 1); buf.strcat(s1).strcat(" ").strcat(s2); if (nrefs > 2) buf.strcat(" ..."); } } - return (char*)buf.ptr; + return (const char*)buf.ptr; } void print_cp_entry(int i) { entry& e = debug_u->cp.entries[i]; - char buf[30]; - sprintf(buf, ((uint)e.tag < CONSTANT_Limit)? TAG_NAME[e.tag]: "%d", e.tag); - printf(" %d\t%s %s\n", i, buf, e.string()); + + if ((uint)e.tag < CONSTANT_Limit) { + printf(" %d\t%s %s\n", i, TAG_NAME[e.tag], e.string()); + } else { + printf(" %d\t%d %s\n", i, e.tag, e.string()); + } } void print_cp_entries(int beg, int end) { diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/common-unpack/unpack.h --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.h Mon Apr 06 10:35:43 2015 -0700 @@ -210,7 +210,7 @@ byte* rp; // read pointer (< rplimit <= input.limit()) byte* rplimit; // how much of the input block has been read? julong bytes_read; - int unsized_bytes_read; + size_t unsized_bytes_read; // callback to read at least one byte, up to available input typedef jlong (*read_input_fn_t)(unpacker* self, void* buf, jlong minlen, jlong maxlen); diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp --- a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -81,7 +81,7 @@ int assert_failed(const char* p) { char message[1<<12]; sprintf(message, "@assert failed: %s\n", p); - fprintf(stdout, 1+message); + fprintf(stdout, "%s", 1+message); breakpoint(); unpack_abort(message); return 0; diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp --- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -84,7 +84,7 @@ } // Write data to the ZIP output stream. -void jar::write_data(void* buff, int len) { +void jar::write_data(void* buff, size_t len) { while (len > 0) { int rc = (int)fwrite(buff, 1, len, jarfp); if (rc <= 0) { @@ -323,12 +323,12 @@ // Total number of disks (int) header64[36] = (ushort)SWAP_BYTES(1); header64[37] = 0; - write_data(header64, (int)sizeof(header64)); + write_data(header64, sizeof(header64)); } // Write the End of Central Directory structure. PRINTCR((2, "end-of-directory at %d\n", output_file_offset)); - write_data(header, (int)sizeof(header)); + write_data(header, sizeof(header)); PRINTCR((2, "writing zip comment\n")); // Write the comment. @@ -590,7 +590,7 @@ zstream = NEW(z_stream, 1); u->gzin = this; u->read_input_fn = read_input_via_gzip; - u->gzcrc = crc32(0L, Z_NULL, 0); + u->gzcrc = crc32(0, Z_NULL, 0); } void gunzip::start(int magic) { diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/common-unpack/zip.h --- a/jdk/src/jdk.pack200/share/native/common-unpack/zip.h Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/common-unpack/zip.h Mon Apr 06 10:35:43 2015 -0700 @@ -68,8 +68,8 @@ } // Private Methods - void write_data(void* ptr, int len); - void write_data(bytes& b) { write_data(b.ptr, (int)b.len); } + void write_data(void* ptr, size_t len); + void write_data(bytes& b) { write_data(b.ptr, b.len); } void add_to_jar_directory(const char* fname, bool store, int modtime, int len, int clen, uLong crc); void write_jar_header(const char* fname, bool store, int modtime, diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/libunpack/jni.cpp --- a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -292,7 +292,7 @@ if (uPtr->aborting()) { THROW_IOE(uPtr->get_abort_message()); - return false; + return null; } // We have fetched all the files. @@ -310,7 +310,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) { unpacker* uPtr = get_unpacker(env, pObj, false); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, NULL); + CHECK_EXCEPTION_RETURN_VALUE(uPtr, 0); size_t consumed = uPtr->input_consumed(); free_unpacker(env, pObj, uPtr); return consumed; @@ -320,6 +320,7 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj, jstring pProp, jstring pValue) { unpacker* uPtr = get_unpacker(env, pObj); + CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); CHECK_EXCEPTION_RETURN_VALUE(prop, false); const char* value = env->GetStringUTFChars(pValue, JNI_FALSE); diff -r d47c58140b41 -r 427f83353f73 jdk/src/jdk.pack200/share/native/unpack200/main.cpp --- a/jdk/src/jdk.pack200/share/native/unpack200/main.cpp Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/src/jdk.pack200/share/native/unpack200/main.cpp Mon Apr 06 10:35:43 2015 -0700 @@ -149,31 +149,28 @@ return progname; } -static const char* usage_lines[] = { - "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n", - "\n", - "Unpacking Options\n", - " -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep (default)\n", - " -r, --remove-pack-file remove input file after unpacking\n", - " -v, --verbose increase program verbosity\n", - " -q, --quiet set verbosity to lowest level\n", - " -l{F}, --log-file={F} output to the given log file, or '-' for standard output (default)\n", - " -?, -h, --help print this message\n", - " -V, --version print program version\n", - " -J{X} Java VM argument (ignored)\n", - null -}; +#define USAGE_HEADER "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n" +#define USAGE_OPTIONS \ + "\n" \ + "Unpacking Options\n" \ + " -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep (default)\n" \ + " -r, --remove-pack-file remove input file after unpacking\n" \ + " -v, --verbose increase program verbosity\n" \ + " -q, --quiet set verbosity to lowest level\n" \ + " -l{F}, --log-file={F} output to the given log file, or '-' for standard output (default)\n" \ + " -?, -h, --help print this message\n" \ + " -V, --version print program version\n" \ + " -J{X} Java VM argument (ignored)\n" static void usage(unpacker* u, const char* progname, bool full = false) { // WinMain does not set argv[0] to the progrname progname = (progname != null) ? nbasename(progname) : "unpack200"; - for (int i = 0; usage_lines[i] != null; i++) { - fprintf(u->errstrm, usage_lines[i], progname); - if (!full) { - fprintf(u->errstrm, - "(For more information, run %s --help .)\n", progname); - break; - } + + fprintf(u->errstrm, USAGE_HEADER, progname); + if (full) { + fprintf(u->errstrm, USAGE_OPTIONS); + } else { + fprintf(u->errstrm, "(For more information, run %s --help .)\n", progname); } } diff -r d47c58140b41 -r 427f83353f73 jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/ProblemList.txt Mon Apr 06 10:35:43 2015 -0700 @@ -283,9 +283,6 @@ # jdk_jdi -# 6983531 -com/sun/jdi/BadHandshakeTest.java linux-all,windows-all - # 8004127 com/sun/jdi/RedefineImplementor.sh generic-all diff -r d47c58140b41 -r 427f83353f73 jdk/test/TEST.groups --- a/jdk/test/TEST.groups Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/TEST.groups Mon Apr 06 10:35:43 2015 -0700 @@ -38,7 +38,9 @@ :jdk_time \ :jdk_security \ :jdk_text \ - :core_tools + :core_tools \ + :jdk_other \ + :jdk_svc ############################################################################### # diff -r d47c58140b41 -r 427f83353f73 jdk/test/com/sun/jdi/BadHandshakeTest.java --- a/jdk/test/com/sun/jdi/BadHandshakeTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/com/sun/jdi/BadHandshakeTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -21,22 +21,15 @@ * questions. */ -/* @test - * @bug 6306165 6432567 - * @summary Check that a bad handshake doesn't cause a debuggee to abort - * @library /lib/testlibrary - * - * @build jdk.testlibrary.* VMConnection BadHandshakeTest Exit0 - * @run driver BadHandshakeTest - * - */ import java.net.Socket; -import java.net.InetAddress; + import com.sun.jdi.Bootstrap; import com.sun.jdi.VirtualMachine; import com.sun.jdi.event.*; import com.sun.jdi.connect.Connector; import com.sun.jdi.connect.AttachingConnector; +import com.sun.jdi.connect.Connector.Argument; + import java.util.Map; import java.util.List; import java.util.Iterator; @@ -46,13 +39,22 @@ import jdk.testlibrary.Utils; import jdk.testlibrary.ProcessTools; +/* @test + * @bug 6306165 6432567 + * @summary Check that a bad handshake doesn't cause a debuggee to abort + * @library /lib/testlibrary + * + * @build jdk.testlibrary.* VMConnection BadHandshakeTest Exit0 + * @run driver BadHandshakeTest + */ public class BadHandshakeTest { + /* * Find a connector by name */ private static Connector findConnector(String name) { - List connectors = Bootstrap.virtualMachineManager().allConnectors(); - Iterator iter = connectors.iterator(); + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); while (iter.hasNext()) { Connector connector = (Connector)iter.next(); if (connector.name().equals(name)) { @@ -65,7 +67,7 @@ /* * Launch a server debuggee with the given address */ - private static Process launch(String address, String class_name) throws Exception { + private static LaunchResult launch(String address, String class_name) throws Exception { String[] args = VMConnection.insertDebuggeeVMOptions(new String[] { "-agentlib:jdwp=transport=dt_socket" + ",server=y" + ",suspend=y" + ",address=" + address, @@ -75,6 +77,7 @@ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); final AtomicBoolean success = new AtomicBoolean(); + final AtomicBoolean bindFailed = new AtomicBoolean(); Process p = ProcessTools.startProcess( class_name, pb, @@ -83,13 +86,17 @@ // Listening for transport dt_socket at address: xxxxx // which shows the debuggee is ready to accept connections. success.set(line.contains("Listening for transport dt_socket at address:")); + // If the first line contains 'Address already in use' + // that means the debuggee has failed to start due to busy port + bindFailed.set(line.contains("Address already in use")); return true; }, Integer.MAX_VALUE, TimeUnit.MILLISECONDS ); - return success.get() ? p : null; + return new LaunchResult(success.get() ? p : null, + bindFailed.get()); } /* @@ -99,14 +106,20 @@ * - verify we saw no error */ public static void main(String args[]) throws Exception { - int port = Utils.getFreePort(); - - String address = String.valueOf(port); - - // launch the server debuggee - Process process = launch(address, "Exit0"); - if (process == null) { - throw new RuntimeException("Unable to start debugee"); + // Launch the server debuggee + int port = 0; + Process process = null; + while (process == null) { + port = Utils.getFreePort(); + String address = String.valueOf(port); + LaunchResult launchResult = launch(address, "Exit0"); + process = launchResult.getProcess(); + if (launchResult.isBindFailed()) { + System.out.println("Port " + port + " already in use. Trying to restart debuggee with a new one..."); + Thread.sleep(100); + } else if (process == null ) { + throw new RuntimeException("Unable to start debugee"); + } } // Connect to the debuggee and handshake with garbage @@ -119,9 +132,9 @@ s.getOutputStream().write("JDWP-".getBytes("UTF-8")); - // attach to server debuggee and resume it so it can exit + // Attach to server debuggee and resume it so it can exit AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach"); - Map conn_args = conn.defaultArguments(); + Map conn_args = conn.defaultArguments(); Connector.IntegerArgument port_arg = (Connector.IntegerArgument)conn_args.get("port"); port_arg.setValue(port); @@ -143,4 +156,24 @@ process.waitFor(); } + private static class LaunchResult { + + private final Process p; + private final boolean bindFailed; + + public LaunchResult(Process p, boolean bindFailed) { + this.p = p; + this.bindFailed = bindFailed; + } + + public Process getProcess() { + return p; + } + + public boolean isBindFailed() { + return bindFailed; + } + + } + } diff -r d47c58140b41 -r 427f83353f73 jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java --- a/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java Mon Apr 06 10:35:43 2015 -0700 @@ -43,11 +43,16 @@ void test(String[] args) throws IOException { SocketAddress address = null; + String os = System.getProperty("os.name").toLowerCase(); if (!Util.isSCTPSupported()) { out.println("SCTP protocol is not supported"); out.println("Test cannot be run"); return; + } else if (os.startsWith("sunos")) { + out.println("Test not supported on Solaris"); + out.println("Test cannot be run"); + return; } System.out.println("remote address: " + remoteAddress); diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/lang/ProcessBuilder/Basic.java --- a/jdk/test/java/lang/ProcessBuilder/Basic.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Mon Apr 06 10:35:43 2015 -0700 @@ -27,6 +27,7 @@ * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464 + * 8067796 * @summary Basic tests for Process and Environment Variable code * @run main/othervm/timeout=300 Basic * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic @@ -2387,6 +2388,56 @@ } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- + // Check that Process.waitFor(timeout, null) throws NPE. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("sleep"); + final Process p = new ProcessBuilder(childArgs).start(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + // Terminate process and recheck after it exits + p.destroy(); + p.waitFor(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // Check that default implementation of Process.waitFor(timeout, null) throws NPE. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("sleep"); + final Process proc = new ProcessBuilder(childArgs).start(); + final DelegatingProcess p = new DelegatingProcess(proc); + + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + // Terminate process and recheck after it exits + p.destroy(); + p.waitFor(); + THROWS(NullPointerException.class, + () -> p.waitFor(10L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(0L, null)); + THROWS(NullPointerException.class, + () -> p.waitFor(-1L, null)); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- // Check the default implementation for // Process.waitFor(long, TimeUnit) //---------------------------------------------------------------- diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/nio/Buffer/genBasic.sh --- a/jdk/test/java/nio/Buffer/genBasic.sh Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/nio/Buffer/genBasic.sh Mon Apr 06 10:35:43 2015 -0700 @@ -1,7 +1,7 @@ #! /bin/sh # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java +javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java gen() { java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 Basic$2.java diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/nio/Buffer/genCopyDirectMemory.sh --- a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Mon Apr 06 10:35:43 2015 -0700 @@ -1,7 +1,7 @@ #! /bin/sh # -# Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java +javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java > Spp.java gen() { java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3CopyDirect$2Memory.java diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Mon Apr 06 10:35:43 2015 -0700 @@ -25,7 +25,6 @@ * @bug 4607272 6842687 6878369 6944810 7023403 * @summary Unit test for AsynchronousSocketChannel * @run main Basic -skipSlowConnectTest - * @key intermittent */ import java.nio.ByteBuffer; diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/nio/channels/Selector/Wakeup.java --- a/jdk/test/java/nio/channels/Selector/Wakeup.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/nio/channels/Selector/Wakeup.java Mon Apr 06 10:35:43 2015 -0700 @@ -25,7 +25,6 @@ * @bug 6405995 * @summary Unit test for selector wakeup and interruption * @library .. - * @key intermittent */ import java.io.*; diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/nio/file/Files/InterruptCopy.java --- a/jdk/test/java/nio/file/Files/InterruptCopy.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/nio/file/Files/InterruptCopy.java Mon Apr 06 10:35:43 2015 -0700 @@ -25,7 +25,6 @@ * @bug 4313887 6993267 * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option * @library .. - * @key intermittent */ import java.nio.file.*; diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.System.out; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Base64; +import java.util.Enumeration; + +/* + * @test + * @bug 8048618 + * @summary Write different types p12 key store to Check the write related + * APIs. + * @run main WriteP12Test + */ + +public class WriteP12Test { + + private static final String IN_KEYSTORE_TYPE = "jks"; + private static final String IN_KEYSTORE_PRV = "SUN"; + + private static final String IN_KEYSTORE_ENDUSER = "keystoreEU.jks.data"; + private static final String IN_KEYSTORE_CA = "keystoreCA.jks.data"; + private static final String OUT_KEYSTORE = "outKeyStore.p12"; + + private static final String IN_STORE_PASS = "storepass"; + private static final String IN_KEY_PASS = "keypass"; + + private static final String CERT_PATH = System.getProperty("test.src", ".") + + File.separator + "certs" + File.separator + "writeP12" + + File.separator; + + private static final String CA_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIIDFzCCAf8CBD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCV\n" + + "VMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUU\n" + + "UxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAwNTUxMlo\n" + + "XDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEph\n" + + "dmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ\n" + + "1MxMiBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ\n" + + "EAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG00yi9aL\n" + + "SsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7I\n" + + "wRTYYy9clFkeeK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4e\n" + + "f1mUASo6+dea0UZA/FHCuV7O6z3hr5VHlyhJL2/o/8M5tGBTBISODJSnn\n" + + "GNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1XnIkiiXR3\n" + + "tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0\n" + + "dQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhx\n" + + "i18YQc2LPWBDLYTTxoFEazWmYLv1k/JT7Nta1qu1quvxXJ4uV1XHbd9NF\n" + + "AJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhqvO03G0Q\n" + + "imhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Yb\n" + + "k5qe3lviMZPkkSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUr\n" + + "sVOVWh7IBCqC/V7FqUTkmD1IFlzkkinatpl42s1MbhJId2yQkzaeBRc\n" + + "suE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di\n" + + "-----END CERTIFICATE-----"; + private static final String LEAD_CERT = "-----BEGIN CERTIFICATE-----\n" + + "MIICwDCCAaigAwIBAgIEPz7S1jANBgkqhkiG9w0BAQQFADBQMQswCQYDV\n" + + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n" + + "R5IFNRRTEXMBUGA1UEAxMOUEtDUzEyIFRlc3QgQ0EwHhcNMDAwODA5MDc\n" + + "wMDAwWhcNMTAwODA3MDcwMDAwWjBSMQswCQYDVQQGEwJVUzERMA8GA1UE\n" + + "ChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaXR5IFNRRTEZMBcGA1UEA\n" + + "xMQUEtDUzEyIFRlc3QgTGVhZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgY\n" + + "kCgYEAzq9X2USz/WjDhT+jUyZWqB5h4A33tS11YqH5qYvqjTXjcUI6gOp\n" + + "moXMafDG9RHRlIccvp51xLp7Ap3WMrv411lWBttqtZi5c1/DEC1cEM/Sl\n" + + "PCk1r2zFbkJu7QKieXeMcrjZEo6LcBHMwQjIpI+up9cr3VjuyqG/olQkU\n" + + "mXVuS0CAwEAAaMkMCIwDwYDVR0PAQH/BAUDAweAADAPBgNVHRMBAf8EBT\n" + + "ADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBhbuim98TWmtv9vSldRE7RvQ8\n" + + "FlS0TyZVO7kcSNtfCUE4R76J1ElN74Koc5pQnUtduLeQJs2ao/mEcCZsE\n" + + "zVcwI3mSZrSzPhc8s7w5gOQA4TUwVLSSjKgBCaZ7R3+qJ3QeqPJ5O6sFz\n" + + "pvBYkgSa4MWptK41jbmT8cwZQJXFCi8WxFFJ+p97F1Ppm3LgmYmtiUP4M\n" + + "ZQwOBvpTZWXU0WrqFXpzWQx0mg4SX19fZm4nLcJAerCEUphf8ILagtpQM\n" + + "EErT3/jg6mfCdT3Rj055QXPfF4OiRFevPF5a1fZgrCePCukRQZcd7s8K5\n" + + "OBIaryuM0MdFtlzxi6XWeUNpVFFHURcy\n" + + "-----END CERTIFICATE-----"; + private static final String END_CERT = "-----BEGIN CERTIFICATE-----\n" + + "MIICNjCCAZ+gAwIBAgIEPz7WtzANBgkqhkiG9w0BAQQFADBSMQswCQYDV\n" + + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n" + + "R5IFNRRTEZMBcGA1UEAxMQUEtDUzEyIFRlc3QgTGVhZDAeFw0wMDA4MDk\n" + + "wNzAwMDBaFw0xMDA4MDcwNzAwMDBaMFgxCzAJBgNVBAYTAlVTMREwDwYD\n" + + "VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMR8wHQYDV\n" + + "QQDExZQS0NTMTIgVGVzdCBFbmQgVXNlciAxMIGfMA0GCSqGSIb3DQEBAQ\n" + + "UAA4GNADCBiQKBgQDIKomSYomDzH/V63eDQEG7od0DLcnnVZ81pbWhDss\n" + + "8gHV2m8pADdRqdihBmnSQEaMW4D3uZ4sFE1LtkQls6hjd7SdOsG5Y24L8\n" + + "15jot9a2JcB73H8H0VKirrObL5BZdt7BtASPDnYtW4Spt++YjDoJFxyF0\n" + + "HchkavzXaVTlexakwIDAQABoxMwETAPBgNVHQ8BAf8EBQMDB4AAMA0GCS\n" + + "qGSIb3DQEBBAUAA4GBAIFA3JXEmb9AXn3RD7t+Mn6DoyVDIy5jsn6xOKT\n" + + "JV25I0obpDUzgw4QaAMmM0ZvusOmZ2wZNS8MtyTUgdANyakbzn5SdxbTy\n" + + "TLEqQsFbX8UVC38fx5ZM6ExA5YSAvgmXudZpOVC0ATccoZS3JFU8CxSfW\n" + + "+Q3IC2MLh+QTg3hUJ5b\n-----END CERTIFICATE-----"; + + private final Certificate testerCert; + private final Certificate testLeadCert; + private final Certificate caCert; + + WriteP12Test() throws CertificateException { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + caCert = cf.generateCertificate(new ByteArrayInputStream(CA_CERT_STR + .getBytes())); + testLeadCert = cf.generateCertificate(new ByteArrayInputStream( + LEAD_CERT.getBytes())); + testerCert = cf.generateCertificate(new ByteArrayInputStream(END_CERT + .getBytes())); + } + + public static void main(String[] args) throws CertificateException, + UnrecoverableKeyException, KeyStoreException, + NoSuchProviderException, NoSuchAlgorithmException, IOException { + WriteP12Test jstest = new WriteP12Test(); + out.println("test WriteP12CertChain"); + /* + * WriteP12CertChain: This test creates a p12 keystore contains one + * entry with private key and a certificate chains contains three + * certificates in the order of user->lead->ca. This case expects to + * pass. + */ + jstest.test(new Certificate[] { jstest.testerCert, jstest.testLeadCert, + jstest.caCert }, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", + "pass", "pass"); + + /* + * WriteP12CertChainBad: same as WriteP12CertChain but chains order is + * user-ca-lead, the order is wrong so expects to fail. + */ + out.println("test WriteP12CertChainBad"); + try { + jstest.test(new Certificate[] { jstest.testerCert, jstest.caCert, + jstest.testLeadCert }, IN_KEYSTORE_ENDUSER, + "pkcs12testenduser1", "pass", "pass"); + throw new RuntimeException( + " Certificate chain is not valid, test should not pass." + + " Test failed."); + } catch (KeyStoreException e) { + e.printStackTrace(); + out.println(" Certificate chain is not valid,exception is" + + " expected. Test passed."); + } + /* + * WriteP12PrivateKey:This test creates a p12 contains a self-signed + * cert and private key,expects no exception + */ + out.println("test WriteP12PrivateKey"); + jstest.test(null, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", "pass", + "pass"); + + /* + * WriteP12TwoEntry: This test creates a p12 keystore with different + * storepass and keypass, and contains two entries. + */ + out.println("test WriteP12TwoEntry"); + jstest.testTwoEntry(IN_KEYSTORE_ENDUSER, IN_KEYSTORE_CA, + "pkcs12testenduser1", "pass", "pass"); + /* + * WriteP12TwoPass: This test creates a p12 keystore with different + * storepass and keypass, and contains one entry with private key and a + * certificate + */ + out.println("test WriteP12TwoPass"); + jstest.test(null, IN_KEYSTORE_CA, "pkcs12testCA", "storepass", + "keypass"); + } + + private void test(Certificate certs[], String inKeyStorePath, + String userAlias, String outStorePass, String outKeyPass) + throws KeyStoreException, NoSuchProviderException, IOException, + CertificateException, UnrecoverableKeyException, + NoSuchAlgorithmException { + // init output key store + KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE"); + outputKeyStore.load(null, null); + try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE)) { + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need + // decode first. + byte[] input = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStorePath)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(input)); + // input key store + KeyStore inputKeyStore = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray()); + // add key/certificate to output key store + Key key = inputKeyStore + .getKey(userAlias, IN_KEY_PASS.toCharArray()); + out.println("Input Key Algorithm " + key.getAlgorithm()); + out.println("====Input Certs====="); + if (certs == null) { + certs = new Certificate[] { inputKeyStore + .getCertificate(userAlias) }; + } + for (Certificate cert : certs) { + out.println(((X509Certificate) cert).getSubjectDN()); + } + outputKeyStore.setKeyEntry(userAlias, key, + outKeyPass.toCharArray(), certs); + Certificate retCerts[] = outputKeyStore + .getCertificateChain(userAlias); + out.println("====Output Certs====="); + for (Certificate retCert : retCerts) { + out.println(((X509Certificate) retCert).getSubjectDN()); + } + out.println("====Output Key Algorithm====="); + Key outKey = outputKeyStore.getKey(userAlias, + outKeyPass.toCharArray()); + out.println(outKey.getAlgorithm()); + + if (!key.equals(outKey)) { + throw new RuntimeException("key don't match"); + } + if (!Arrays.equals(certs, retCerts)) { + throw new RuntimeException("certs don't match"); + } + // save output + outputKeyStore.store(fout, outStorePass.toCharArray()); + // test output + testKeyStore(outputKeyStore, outKeyPass.toCharArray()); + } + } + + private void testTwoEntry(String inKeyStoreOnePath, + String inKeyStoreTwoPath, String userAlias, String outStorePass, + String outKeyPass) throws KeyStoreException, + NoSuchProviderException, NoSuchAlgorithmException, + CertificateException, IOException, UnrecoverableKeyException { + // initial KeyStore + KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE"); + try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE);) { + outputKeyStore.load(null, null); + KeyStore inputKeyStoreOne, inputKeyStoreTwo; + inputKeyStoreOne = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need + // decode first. + byte[] inputBytes = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStoreOnePath)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(inputBytes)); + // input key store + inputKeyStoreOne.load(arrayIn, IN_STORE_PASS.toCharArray()); + + inputBytes = Files.readAllBytes(Paths.get(CERT_PATH, + inKeyStoreTwoPath)); + arrayIn = new ByteArrayInputStream(Base64.getMimeDecoder().decode( + inputBytes)); + inputKeyStoreTwo = KeyStore.getInstance(IN_KEYSTORE_TYPE, + IN_KEYSTORE_PRV); + inputKeyStoreTwo.load(arrayIn, IN_STORE_PASS.toCharArray()); + + // add key/certificate to output key store + out.println("====First Entry====="); + Key inputKey = inputKeyStoreOne.getKey(userAlias, + IN_KEY_PASS.toCharArray()); + Certificate cert = inputKeyStoreOne.getCertificate(userAlias); + Certificate certs[] = new Certificate[1]; + certs[0] = cert; + + out.println("====Input1 Key====="); + out.println(inputKey.getAlgorithm()); + out.println("====Input1 Certs====="); + out.println("Certificate :"); + out.println(((X509Certificate) cert).getSubjectDN()); + outputKeyStore.setKeyEntry("USER", inputKey, + outKeyPass.toCharArray(), certs); + out.println("====Second Entry====="); + String caAlias = "pkcs12testca"; + inputKey = inputKeyStoreTwo.getKey(caAlias, + IN_KEY_PASS.toCharArray()); + cert = inputKeyStoreTwo.getCertificate(caAlias); + certs[0] = cert; + out.println("====Input2 Key====="); + out.println(inputKey.getAlgorithm()); + out.println("====Input2 Certs====="); + out.println("Certificate :"); + out.println(((X509Certificate) cert).getSubjectDN()); + outputKeyStore.setKeyEntry("CA", inputKey, + outKeyPass.toCharArray(), certs); + // save output + outputKeyStore.store(fout, outStorePass.toCharArray()); + // test output + testKeyStore(outputKeyStore, outKeyPass.toCharArray()); + } + } + + private void testKeyStore(KeyStore inputKeyStore, char[] keypass) + throws KeyStoreException, UnrecoverableKeyException, + NoSuchAlgorithmException { + out.println("========== Key Store =========="); + out.println("getProvider : " + inputKeyStore.getProvider()); + out.println("getType : " + inputKeyStore.getType()); + out.println("getDefaultType : " + KeyStore.getDefaultType()); + + int idx = 0; + Enumeration e = inputKeyStore.aliases(); + String alias; + while (e.hasMoreElements()) { + alias = e.nextElement(); + if (!inputKeyStore.containsAlias(alias)) { + throw new RuntimeException("Alias not found"); + } + out.println("Alias " + idx + " : " + alias); + out.println("getCreationDate : " + + inputKeyStore.getCreationDate(alias)); + X509Certificate cert = (X509Certificate) inputKeyStore + .getCertificate(alias); + out.println("getCertificate : " + cert.getSubjectDN()); + String retAlias = inputKeyStore.getCertificateAlias(cert); + if (!retAlias.equals(alias)) { + throw new RuntimeException("Alias mismatch, actually " + + retAlias + ", expected " + alias); + } + out.println("getCertificateAlias : " + retAlias); + Certificate[] certs = inputKeyStore.getCertificateChain(alias); + int i = 0; + for (Certificate certification : certs) { + out.println("getCertificateChain " + i + + ((X509Certificate) certification).getSubjectDN()); + i++; + } + if (inputKeyStore.isCertificateEntry(alias)) { + throw new RuntimeException( + "inputKeystore should not be certEntry because this" + + " keystore only contain key pair entries."); + } + if (!inputKeyStore.isKeyEntry(alias)) { + throw new RuntimeException("Entry type unknown."); + } + idx++; + } + int size = inputKeyStore.size(); + if (idx != size) { + throw new RuntimeException("Size not match, actually " + idx + + ", expected " + size); + } + } + +} diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreCA.jks.data Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,38 @@ +/u3+7QAAAAIAAAABAAAAAQAMcGtjczEydGVzdGNhAAAA9w1mDAMAAAUCMIIE/jAOBgorBgEEASoC +EQEBBQAEggTqFhceJz85XyVsicsfonXYx+vvFXkb9Jmr11eh9n570ZdiFZ1hv4XRk/x/1C1spy5X +J2wv4lABGAOA5gV0aTKij+82NLoEz9zDW5fwAnrBKVjAq/NxdwEi9lvipiSVx1qglx/mQAHeEi4i +6vDoai3hVNQqVmd/TG2deyk/fQ9MZ7U2fmWcJDH4YbP39psQ+7rp9cDJ0P7GWoLXwbWs1vftbN0R +4fWitH1+6hBbIbVT9o0cM9ilAjpkNFr10pBEsfrikaE8IsN562soWfNxGwwrsjExEFeKlMrtNtWM +Wc4+YZ1ybVi/6krK/kFfOa+R3mtjBoD7zM4TSG9dptuvBLVgey8RXh3BQ8pU7uN5q+9Omqo1SsRN +wHYKjTrfWMozt+37ZlyCZ70Kb/2jJYWFuo9+wqXQU+MYnpZZB+cLt3PIFMakhIu1vpMpJCcoceaS +bjDWxCG8HHZjjFJPxAE3HEbCzaj4BevxQfxtp57llmtI2I0NJvua8JbFjf0U9MK6iRi4IpmBztpP +vxvaetT54wC+2c0QaDqANIn3Oc4tmvD4RGJfmFrEYEX6dQbCwYHAJF8sczqDb4xIYwrGmiMNeeha +4g9fcEa7Q+t1o1XLmNOp5e6I/TjUfXGvKlEyYeQ1FNLRqTtI5KvHQ1l71n1aQyEPvcff93NlF3jv +jWuqOqLzFT7sIZQxgjoum4i0DwLzOtuAWIDELNJ03MCciq5j0SjoLO2/ISctNTyGuYBmerjGCI9c +CLhGYnwLCOvvZN1yIqT79Se6qe/tBV5nEYUdXEt4ROJNabf1H4GmkXYeDQvtHrQ1IHM+Kg1UyEJz +fwdhJ68EU3gFenTtFgVJ+90YpemGtptgS6CvS3qC2H/H3XaKKQGpsXRCMSCRZcfMMOQEc6WLPsVY +rEhorQIAbbgHp4//H+RkNzG+5NN4pac5bo0kDTpeQkiOXGZZKyMHgagFvwLCN35rTi2HnHEXnYoi +jU1sGmUV+kRgRJ+N3Gx6D+uWNctkZMeTuVg+9ftIhEClGdtBSXWZu9lr/48cXkWJBubd4CWYrFMm +cTYezlQiTvmQgodrrwtcdo17J/L4PK74C72aIqPlWdEImGQs7I4n1mvceXoHvjYu5+tOxS0HH4sm +Y4iMr3hsqVAag2/LeLCG1gumpGiTdh9hk/aOcSWASv7rjq8JVpxWJe3JbrQ5k0U3e1nE2AdSXjEj +knBDpDFpGsnJaP2xxTdvQ+oV1pZ3m30xOeCTVV+0VBIw8eL0PDATSgqQ7FuWnYZ/FGaOrgnn14JM +HQicEfFN7TOa8q3/lbY5JTRtuG5umoWL2AWaaAW6G5GRTUNMOvBI5xTvR/kr3iNKTK2caKi0XTJ3 +WXd9jeuyLstpbtokG6xBbSiAb/SSL9yoh400DbKFTlVHKD8cijfuLKIM1TmL2ZksEh6JvF8GfdLl +FXZH7Ny8aJ63Ef947P9Y8+6WMzZDrkyoV+uInRq1TVXk6Ps6qiqI0j9fhMI8XMju61vjkeXprzBE +Pk2GbXo7MtHrBTobffkD3BszrFJai8n9vDrQgsaZYwWi4IxlKYefmWDaagiq/qDBZhKQCgyuJNN/ +5sQZDb6+J/MIgDk0M2bXEs6f2gT1rAyuH+rbnsnfUu9jRQupP4q0/ZCY2WOIaf8W34FnMdNzOUH8 +iE2T59UbMGQ0DLJeHwAAAAEABVguNTA5AAADGzCCAxcwggH/AgQ/PtJwMA0GCSqGSIb3DQEBBQUA +MFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FF +MRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTAeFw0wMzA4MTcwMDU1MTJaFw0xMzA4MTQwMDU1MTJa +MFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FF +MRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJO0ofiv8hrJiWnGZ435GX7lsRjSQj1tKuvXscKET/ngRzEMBtNMovWi0rGQKjaSUgg76YMkjgFJ +gXfn/FhYR6iX0VURFX795q2nQymQo4arbFCOyMEU2GMvXJRZHniuHR2sW7hTD6VLu8kH8Ek14Lzg +P1CeJCbhrWmAHUySOHn9ZlAEqOvnXmtFGQPxRwrlezus94a+VR5coSS9v6P/DObRgUwSEjgyUp5x +jQb7UCzR51mL7OO9FABNgbbghmIdVf9xwB9bUYq0tzAQXG9V5yJIol0d7Y2gUgfl4aAn7hvCrSJ1 +1xWgJ7yn2PZmBcOlSbfSWEKWNlQwu9vNfz289HUCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAc12f +Mx1q5wvPxPjf59gs4cYtfGEHNiz1gQy2E08aBRGs1pmC79ZPyU+zbWtartarr8VyeLldVx23fTRQ +CVisLRUBKX7+KOiO6llD6MZ3wPo8qil8b9u89ubc7fmOMThIarztNxtEIpoZIjbfTBey+vctlNP1 +O9/rhTRs3QBA4iPRIm7yAojp69U3kORnpCt2G5Oant5b4jGT5JEl3qUySPJtAIlwo4vnl4/e41S3 +h/kcXgXIQWPrhC66lK7FTlVoeyAQqgv1exalE5Jg9SBZc5JIp2raZeNrNTG4SSHdskJM2ngUXLLh +Ot2wxLbkVqfcpzDt0AOGLvObgUVhs0NQ4nYQH5SPMKBNY+nGGfmMLaFPAelF \ No newline at end of file diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/writeP12/keystoreEU.jks.data Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,79 @@ +/u3+7QAAAAIAAAADAAAAAgAMcGtjczEydGVzdGNhAAAA9w18bwQABVguNTA5AAADGzCCAxcwggH/ +AgQ/PtJwMA0GCSqGSIb3DQEBBQUAMFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEV +MBMGA1UECxMMU2VjdXJpdHkgU1FFMRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTAeFw0wMzA4MTcw +MDU1MTJaFw0xMzA4MTQwMDU1MTJaMFAxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhKYXZhU29mdDEV +MBMGA1UECxMMU2VjdXJpdHkgU1FFMRcwFQYDVQQDEw5QS0NTMTIgVGVzdCBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJO0ofiv8hrJiWnGZ435GX7lsRjSQj1tKuvXscKET/ngRzEM +BtNMovWi0rGQKjaSUgg76YMkjgFJgXfn/FhYR6iX0VURFX795q2nQymQo4arbFCOyMEU2GMvXJRZ +HniuHR2sW7hTD6VLu8kH8Ek14LzgP1CeJCbhrWmAHUySOHn9ZlAEqOvnXmtFGQPxRwrlezus94a+ +VR5coSS9v6P/DObRgUwSEjgyUp5xjQb7UCzR51mL7OO9FABNgbbghmIdVf9xwB9bUYq0tzAQXG9V +5yJIol0d7Y2gUgfl4aAn7hvCrSJ11xWgJ7yn2PZmBcOlSbfSWEKWNlQwu9vNfz289HUCAwEAATAN +BgkqhkiG9w0BAQUFAAOCAQEAc12fMx1q5wvPxPjf59gs4cYtfGEHNiz1gQy2E08aBRGs1pmC79ZP +yU+zbWtartarr8VyeLldVx23fTRQCVisLRUBKX7+KOiO6llD6MZ3wPo8qil8b9u89ubc7fmOMThI +arztNxtEIpoZIjbfTBey+vctlNP1O9/rhTRs3QBA4iPRIm7yAojp69U3kORnpCt2G5Oant5b4jGT +5JEl3qUySPJtAIlwo4vnl4/e41S3h/kcXgXIQWPrhC66lK7FTlVoeyAQqgv1exalE5Jg9SBZc5JI +p2raZeNrNTG4SSHdskJM2ngUXLLhOt2wxLbkVqfcpzDt0AOGLvObgUVhs0NQ4gAAAAIADnBrY3Mx +MnRlc3RsZWFkAAAA9w1+meMABVguNTA5AAACxDCCAsAwggGooAMCAQICBD8+0tYwDQYJKoZIhvcN +AQEEBQAwUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0 +eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3 +MDAwMFowUjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0 +eSBTUUUxGTAXBgNVBAMTEFBLQ1MxMiBUZXN0IExlYWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ +AoGBAM6vV9lEs/1ow4U/o1MmVqgeYeAN97UtdWKh+amL6o0143FCOoDqZqFzGnwxvUR0ZSHHL6ed +cS6ewKd1jK7+NdZVgbbarWYuXNfwxAtXBDP0pTwpNa9sxW5Cbu0Conl3jHK42RKOi3ARzMEIyKSP +rqfXK91Y7sqhv6JUJFJl1bktAgMBAAGjJDAiMA8GA1UdDwEB/wQFAwMHgAAwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAYW7opvfE1prb/b0pXURO0b0PBZUtE8mVTu5HEjbXwlBO +Ee+idRJTe+CqHOaUJ1LXbi3kCbNmqP5hHAmbBM1XMCN5kma0sz4XPLO8OYDkAOE1MFS0koyoAQmm +e0d/qid0HqjyeTurBc6bwWJIEmuDFqbSuNY25k/HMGUCVxQovFsRRSfqfexdT6Zty4JmJrYlD+DG +UMDgb6U2Vl1NFq6hV6c1kMdJoOEl9fX2ZuJy3CQHqwhFKYX/CC2oLaUDBBK09/44OpnwnU90Y9Oe +UFz3xeDokRXrzxeWtX2YKwnjwrpEUGXHe7PCuTgSGq8rjNDHRbZc8Yul1nlDaVRRR1EXMgAAAAEA +EnBrY3MxMnRlc3RlbmR1c2VyMQAAAPcNgTivAAACuTCCArUwDgYKKwYBBAEqAhEBAQUABIICoU6N +bD6qkNDM8KJFHCTHUevURAV8SUuzzBwsfYC0tEDMa2zGNUEvrmgyM3b5z7qR8XbTZvVBFJJLp3Jx +HmQpg0vLltDFFIPiVgRVcUEDPSmks1KP/bP/mE1uos31R6VyfNMGS3JnQblcSipcB893NrFFXNu2 +PUPjKCC9GrQZAmSM78BBTrwWD/Yd4rKcVh57DLKtUySoF29qXthusJjhSaqRZERaMV6egviE5+W8 +f8ppTYLx2gJmOyi9edJEdHxMcPzRvWgxlmUqUCDg0KVsosbxjjJKcmJ9b1KWuadKyAYkqxSDi8sx +2iwEQW3PQjLGBVHeQNntUF1wapp21sD1lVmDV3+61+fIphAUVRQXjmoYsEhrTc93IkDtQWgfJsgz +xjVVDbcy29VnMAK4f3tT/p5HeFO6yRQBE2B3IngSomRxbNh143VswNYqtZYy03UhOm8vbF2OfOJ/ +NzwC/F+19XgntnC0qv5j6VzwMGTt2NYPWXUqSzVIFswSunj70+ZsprCRX5IEFnpHDSL7OwDjEMFc +z6dpYQ9pwgyKh7JiLZxAr/9Nhb8QQDGrolzHoDt1QnC/DYvDGfTKu0ZjlXR4EQN4XFV+FAiykRfA +N1jIsTY7fCmLpLuW4paQnR1lPSGLeSvi63DOgN+lfVSJ5YjZm4yIRIS6lpvLVgcqodDqBRmPMP7x +fJ3osv1Wt4L/77BdJpZrUUygysRpzyUKlC6NwXr338HKPyAnfrkzIpHKnhTUaRVmfgAuzrXMFp8C +ejyYXJQwPPFAL5mIdUMkLDQKzESI0T3AD1LWVDM/0mGud9GhqiycI6AqC0j7MynRCvQG0LyRunFG +EQ2KipM//qPFKqwoVukxrLTunmGyeOe6UxodtK+qcn7SIXZ8jJM14a5rSDwAAAADAAVYLjUwOQAA +AjowggI2MIIBn6ADAgECAgQ/Pta3MA0GCSqGSIb3DQEBBAUAMFIxCzAJBgNVBAYTAlVTMREwDwYD +VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMRkwFwYDVQQDExBQS0NTMTIgVGVz +dCBMZWFkMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3MDAwMFowWDELMAkGA1UEBhMCVVMxETAP +BgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxHzAdBgNVBAMTFlBLQ1MxMiBU +ZXN0IEVuZCBVc2VyIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMgqiZJiiYPMf9Xrd4NA +Qbuh3QMtyedVnzWltaEOyzyAdXabykAN1Gp2KEGadJARoxbgPe5niwUTUu2RCWzqGN3tJ06wbljb +gvzXmOi31rYlwHvcfwfRUqKus5svkFl23sG0BI8Odi1bhKm375iMOgkXHIXQdyGRq/NdpVOV7FqT +AgMBAAGjEzARMA8GA1UdDwEB/wQFAwMHgAAwDQYJKoZIhvcNAQEEBQADgYEAgUDclcSZv0BefdEP +u34yfoOjJUMjLmOyfrE4pMlXbkjShukNTODDhBoAyYzRm+6w6ZnbBk1Lwy3JNSB0A3JqRvOflJ3F +tPJMsSpCwVtfxRULfx/HlkzoTEDlhIC+CZe51mk5ULQBNxyhlLckVTwLFJ9b5DcgLYwuH5BODeFQ +nlsABVguNTA5AAACxDCCAsAwggGooAMCAQICBD8+0tYwDQYJKoZIhvcNAQEEBQAwUDELMAkGA1UE +BhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMT +DlBLQ1MxMiBUZXN0IENBMB4XDTAwMDgwOTA3MDAwMFoXDTEwMDgwNzA3MDAwMFowUjELMAkGA1UE +BhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxGTAXBgNVBAMT +EFBLQ1MxMiBUZXN0IExlYWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM6vV9lEs/1ow4U/ +o1MmVqgeYeAN97UtdWKh+amL6o0143FCOoDqZqFzGnwxvUR0ZSHHL6edcS6ewKd1jK7+NdZVgbba +rWYuXNfwxAtXBDP0pTwpNa9sxW5Cbu0Conl3jHK42RKOi3ARzMEIyKSPrqfXK91Y7sqhv6JUJFJl +1bktAgMBAAGjJDAiMA8GA1UdDwEB/wQFAwMHgAAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQQFAAOCAQEAYW7opvfE1prb/b0pXURO0b0PBZUtE8mVTu5HEjbXwlBOEe+idRJTe+CqHOaUJ1LX +bi3kCbNmqP5hHAmbBM1XMCN5kma0sz4XPLO8OYDkAOE1MFS0koyoAQmme0d/qid0HqjyeTurBc6b +wWJIEmuDFqbSuNY25k/HMGUCVxQovFsRRSfqfexdT6Zty4JmJrYlD+DGUMDgb6U2Vl1NFq6hV6c1 +kMdJoOEl9fX2ZuJy3CQHqwhFKYX/CC2oLaUDBBK09/44OpnwnU90Y9OeUFz3xeDokRXrzxeWtX2Y +KwnjwrpEUGXHe7PCuTgSGq8rjNDHRbZc8Yul1nlDaVRRR1EXMgAFWC41MDkAAAMbMIIDFzCCAf8C +BD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUw +EwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAw +NTUxMloXDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEphdmFTb2Z0MRUw +EwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG +00yi9aLSsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7IwRTYYy9clFke +eK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4ef1mUASo6+dea0UZA/FHCuV7O6z3hr5V +HlyhJL2/o/8M5tGBTBISODJSnnGNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1Xn +IkiiXR3tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0dQIDAQABMA0G +CSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhxi18YQc2LPWBDLYTTxoFEazWmYLv1k/J +T7Nta1qu1quvxXJ4uV1XHbd9NFAJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhq +vO03G0QimhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Ybk5qe3lviMZPk +kSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUrsVOVWh7IBCqC/V7FqUTkmD1IFlzkkin +atpl42s1MbhJId2yQkzaeBRcsuE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di7p2dz0wNRNimbVP4 +VL+NWQOgtME= \ No newline at end of file diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/util/Arrays/TimSortStackSize2.java --- a/jdk/test/java/util/Arrays/TimSortStackSize2.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/util/Arrays/TimSortStackSize2.java Mon Apr 06 10:35:43 2015 -0700 @@ -24,22 +24,63 @@ /* * @test * @bug 8072909 - * @run main/othervm -Xms385m TimSortStackSize2 67108864 + * @library /lib/testlibrary /../../test/lib + * @build jdk.testlibrary.* + * @build TimSortStackSize2 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TimSortStackSize2 * @summary Test TimSort stack size on big arrays - * big tests not for regular execution on all platforms: - * run main/othervm -Xmx8g TimSortStackSize2 1073741824 - * run main/othervm -Xmx16g TimSortStackSize2 2147483644 */ import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import java.util.function.Consumer; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; +import sun.hotspot.WhiteBox; + public class TimSortStackSize2 { public static void main(String[] args) { - int lengthOfTest = Integer.parseInt(args[0]); + if ( args == null || args.length == 0 ){ + startMeWithArgs(); + } else { + doTestOfTwoTimSorts(Integer.parseInt(args[0])); + } + } + + private static void startMeWithArgs(){ + /* + * big tests not for regular execution on all platforms: + * run main/othervm -Xmx8g TimSortStackSize2 1073741824 + * run main/othervm -Xmx16g TimSortStackSize2 2147483644 + */ + try { + Boolean compressedOops = WhiteBox.getWhiteBox() + .getBooleanVMFlag("UseCompressedOops"); + final String xmsValue = "-Xms" + + ((compressedOops == null || compressedOops) ? "385" : "770") + + "m"; + System.out.println( "compressedOops: " + compressedOops + + "; Test will be started with \"" + xmsValue + "\""); + ProcessBuilder processBuilder = ProcessTools + .createJavaProcessBuilder(Utils.addTestJavaOpts(xmsValue, + "TimSortStackSize2", "67108864" + ) + ); + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); + System.out.println(output.getOutput()); + output.shouldHaveExitValue(0); + } catch( Exception e ){ + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + private static void doTestOfTwoTimSorts(final int lengthOfTest){ boolean passed = doTest("TimSort", lengthOfTest, (Integer [] a) -> Arrays.sort(a)); passed = doTest("ComparableTimSort", lengthOfTest, (Integer [] a) -> diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/util/Properties/Basic.java --- a/jdk/test/java/util/Properties/Basic.java Tue Mar 31 16:22:59 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!"); - } - } -} diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/util/Properties/LoadAndStoreNPE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Properties/LoadAndStoreNPE.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Properties; + +/* + * @test + * @bug 8073214 8075362 + * @summary Tests to verify that load() and store() throw NPEs as advertised. + */ +public class LoadAndStoreNPE +{ + public static void main(String[] args) throws Exception + { + int failures = 0; + + Properties props = new Properties(); + + try { + props.store((OutputStream)null, "comments"); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + try { + props.store((Writer)null, "comments"); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + try { + props.load((InputStream)null); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + try { + props.load((Reader)null); + failures++; + } catch (NullPointerException e) { + // do nothing + } + + if (failures != 0) { + throw new RuntimeException("LoadAndStoreNPE failed with " + + failures + " errors!"); + } + } +} diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java --- a/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ final int lastLimitIndex = l; return s -> { - if (lastLimitIndex == -1) + if (lastLimitIndex == -1 && fs.size() > 0) s = fi.apply(s); for (int i = 0; i < fs.size(); i++) { s = fs.get(i).apply(s); diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -24,11 +24,12 @@ /** * @test * @summary Tests counting of streams - * @bug 8031187 8067969 + * @bug 8031187 8067969 8075307 */ package org.openjdk.tests.java.util.stream; +import java.util.HashSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.DoubleStream; import java.util.stream.DoubleStreamTestDataProvider; @@ -59,6 +60,19 @@ terminal(s -> s.filter(e -> true), Stream::count). expectedResult(expectedCount). exercise(); + + // Test with stateful distinct op that is a barrier or lazy + // depending if source is not already distinct and encounter order is + // preserved or not + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(Stream::distinct, Stream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), Stream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) @@ -74,6 +88,16 @@ terminal(s -> s.filter(e -> true), IntStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(IntStream::distinct, IntStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), IntStream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) @@ -89,6 +113,16 @@ terminal(s -> s.filter(e -> true), LongStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(LongStream::distinct, LongStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), LongStream::count). + expectedResult(expectedCount). + exercise(); } @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) @@ -104,6 +138,16 @@ terminal(s -> s.filter(e -> true), DoubleStream::count). expectedResult(expectedCount). exercise(); + + expectedCount = data.into(new HashSet<>()).size(); + withData(data). + terminal(DoubleStream::distinct, DoubleStream::count). + expectedResult(expectedCount). + exercise(); + withData(data). + terminal(s -> s.unordered().distinct(), DoubleStream::count). + expectedResult(expectedCount). + exercise(); } public void testNoEvaluationForSizedStream() { @@ -111,24 +155,36 @@ AtomicInteger ai = new AtomicInteger(); Stream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + Stream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); IntStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + IntStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); LongStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + LongStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } { AtomicInteger ai = new AtomicInteger(); DoubleStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).count(); assertEquals(ai.get(), 0); + + DoubleStream.of(1, 2, 3, 4).peek(e -> ai.getAndIncrement()).parallel().count(); + assertEquals(ai.get(), 0); } } } diff -r d47c58140b41 -r 427f83353f73 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,7 +128,7 @@ @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) public void testDistinctDistinct(String name, TestData.OfRef data) { Collection result = withData(data) - .stream(s -> s.distinct().distinct(), new CollectorOps.TestParallelSizedOp<>()) + .stream(s -> s.distinct().distinct()) .exercise(); assertUnique(result); } diff -r d47c58140b41 -r 427f83353f73 jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java --- a/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,7 +80,7 @@ } try { - urlc.getServerCertificateChain(); + urlc.getServerCertificates(); } catch (IllegalStateException e) { System.out.print("Caught proper exception: "); System.out.println(e.getMessage()); diff -r d47c58140b41 -r 427f83353f73 jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java --- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Mon Apr 06 10:35:43 2015 -0700 @@ -24,6 +24,8 @@ package jdk.testlibrary; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintStream; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; @@ -34,6 +36,7 @@ import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -188,8 +191,8 @@ } else { latch.countDown(); } - Future stdoutTask = stdout.process(); - Future stderrTask = stderr.process(); + final Future stdoutTask = stdout.process(); + final Future stderrTask = stderr.process(); try { if (timeout > -1) { @@ -216,7 +219,7 @@ throw e; } - return p; + return new ProcessImpl(p, stdoutTask, stderrTask); } /** @@ -436,4 +439,84 @@ System.out.println(analyzer.getOutput()); return analyzer; } + + private static class ProcessImpl extends Process { + + private final Process p; + private final Future stdoutTask; + private final Future stderrTask; + + public ProcessImpl(Process p, Future stdoutTask, Future stderrTask) { + this.p = p; + this.stdoutTask = stdoutTask; + this.stderrTask = stderrTask; + } + + @Override + public OutputStream getOutputStream() { + return p.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + return p.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + return p.getErrorStream(); + } + + @Override + public int waitFor() throws InterruptedException { + int rslt = p.waitFor(); + waitForStreams(); + return rslt; + } + + @Override + public int exitValue() { + return p.exitValue(); + } + + @Override + public void destroy() { + p.destroy(); + } + + @Override + public long getPid() { + return p.getPid(); + } + + @Override + public boolean isAlive() { + return p.isAlive(); + } + + @Override + public Process destroyForcibly() { + return p.destroyForcibly(); + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + boolean rslt = p.waitFor(timeout, unit); + if (rslt) { + waitForStreams(); + } + return rslt; + } + + private void waitForStreams() throws InterruptedException { + try { + stdoutTask.get(); + } catch (ExecutionException e) { + } + try { + stderrTask.get(); + } catch (ExecutionException e) { + } + } + } } diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java --- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -90,7 +90,6 @@ } } } - System.err.println("*** port = " + port); ports[i] = port; } return ports; diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java --- a/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java Mon Apr 06 10:35:43 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,8 @@ import java.io.*; import java.net.*; +import java.security.cert.Certificate; import javax.net.ssl.*; -import javax.security.cert.*; import com.sun.net.ssl.HostnameVerifier; import com.sun.net.ssl.HttpsURLConnection; @@ -240,8 +240,8 @@ System.out.println("Cipher Suite: " + ((HttpsURLConnection)urlc).getCipherSuite()); - X509Certificate[] certs = - ((HttpsURLConnection)urlc).getServerCertificateChain(); + Certificate[] certs = + ((HttpsURLConnection)urlc).getServerCertificates(); for (int i = 0; i < certs.length; i++) { System.out.println(certs[0]); } diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/security/mscapi/ShortRSAKey1024.sh --- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh Mon Apr 06 10:35:43 2015 -0700 @@ -30,6 +30,7 @@ # @run shell ShortRSAKey1024.sh 1024 # @run shell ShortRSAKey1024.sh 768 # @run shell ShortRSAKey1024.sh 512 +# @key intermittent # set a few environment variables so that the shell-script can run stand-alone # in the source directory diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh --- a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh Mon Apr 06 10:35:43 2015 -0700 @@ -28,6 +28,7 @@ # @bug 6578658 # @run shell SignUsingNONEwithRSA.sh # @summary Sign using the NONEwithRSA signature algorithm from SunMSCAPI +# @key intermittent # set a few environment variables so that the shell-script can run stand-alone # in the source directory diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/security/provider/X509Factory/BadPem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/provider/X509Factory/BadPem.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8074935 + * @summary jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did + */ + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.Base64; + +import sun.security.provider.X509Factory; +import java.security.cert.CertificateFactory; +import java.io.ByteArrayInputStream; + +public class BadPem { + + public static void main(String[] args) throws Exception { + String ks = System.getProperty("test.src", ".") + + "/../../../../javax/net/ssl/etc/keystore"; + String pass = "passphrase"; + String alias = "dummy"; + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new FileInputStream(ks), pass.toCharArray()); + byte[] cert = keyStore.getCertificate(alias).getEncoded(); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream pout = new PrintStream(bout); + byte[] CRLF = new byte[] {'\r', '\n'}; + pout.println(X509Factory.BEGIN_CERT); + for (int i=0; i i + 48) ? 48 : (cert.length - i); + pout.println("!" + Base64.getEncoder() + .encodeToString(Arrays.copyOfRange(cert, i, i + blockLen))); + } + pout.println(X509Factory.END_CERT); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + try { + cf.generateCertificate(new ByteArrayInputStream(bout.toByteArray())); + throw new Exception("Should fail"); + } catch (CertificateException e) { + // Good + } + } +} + diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/security/tools/keytool/KeyToolTest.java --- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -56,6 +56,8 @@ * NSS PKCS11 config file are changed, DSA not supported now. */ +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; import sun.security.x509.*; import java.io.*; @@ -1222,6 +1224,24 @@ remove("mykey.cert"); } + // 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness + static void checkPem(String file) throws Exception { + boolean maybeLast = false; + for (String s: Files.readAllLines(Paths.get(file))) { + if (s.isEmpty()) continue; + if (s.startsWith("---")) continue; + if (maybeLast) { + throw new Exception("Last line already seen"); + } + if (s.length() > 64) { + throw new Exception(s); + } + if (s.length() < 64) { + maybeLast = true; + } + } + } + void v3extTest(String keyAlg) throws Exception { KeyStore ks; remove("x.jks"); @@ -1588,12 +1608,14 @@ "-rfc -file test.req"); // printcertreq testOK("", "-printcertreq -file test.req"); + checkPem("test.req"); // issue: deny KU, change criticality of 1.2.3 and 1.2.4, // change content of BC, add 2.3.4 testOK("", simple+"-gencert -alias ca -infile test.req -ext " + "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " + "-ext BC=2 -ext 2.3.4=01020304 " + "-debug -rfc -outfile test.cert"); + checkPem("test.cert"); testOK("", simple+"-importcert -file test.cert -alias a"); ks = loadStore("x.jks", "changeit", "JKS"); X509CertImpl a = (X509CertImpl)ks.getCertificate("a"); diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/text/resources/LocaleData --- a/jdk/test/sun/text/resources/LocaleData Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/text/resources/LocaleData Mon Apr 06 10:35:43 2015 -0700 @@ -8279,3 +8279,6 @@ FormatData/fi/DatePatterns/1=d. MMMM yyyy FormatData/fi/DatePatterns/2=d.M.yyyy FormatData/fi/DatePatterns/3=d.M.yyyy + +# bug #8075173 +FormatData/de/standalone.MonthAbbreviations/2=M\u00e4r diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/text/resources/LocaleDataTest.java --- a/jdk/test/sun/text/resources/LocaleDataTest.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/text/resources/LocaleDataTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -36,7 +36,7 @@ * 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495 * 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509 * 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 8017142 - * 8037343 8055222 8042126 8074791 + * 8037343 8055222 8042126 8074791 8075173 * @summary Verify locale data * */ diff -r d47c58140b41 -r 427f83353f73 jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java --- a/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java Tue Mar 31 16:22:59 2015 -0700 +++ b/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java Mon Apr 06 10:35:43 2015 -0700 @@ -417,7 +417,9 @@ setLastModified(theLockFileName, epoch()); Thread.sleep(spinDelay); } - + } catch (NoSuchFileException ex) { + // Lock deleted while we are setting last modified time. + // Ignore error and lets the app exits } catch (Exception ex) { System.err.println("LingeredApp ERROR: " + ex); // Leave exit_code = 1 to Java launcher diff -r d47c58140b41 -r 427f83353f73 langtools/.hgtags --- a/langtools/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/langtools/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -298,3 +298,5 @@ 99ff00581f3633c1787bec21f2a8f3a2ffe57665 jdk9-b53 ed34864f3b43a7df394fce6c3f0bc86b70a5d686 jdk9-b54 32a2e724988499e6f68611a65168c5f2fde0f6b9 jdk9-b55 +5ee7bba6ef41447f921184e8522da36734aec089 jdk9-b56 +ec977a00cecbf0007b0fa26c7af2852d57a79cad jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/ConstructorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ConstructorTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,170 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for constructors. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build ConstructorTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver ConstructorTest + */ + +import java.lang.ref.ReferenceQueue; +import java.util.*; + +@ExpectedSignature(descriptor = "ConstructorTest", signature = "Ljava/lang/Object;") +public class ConstructorTest { + + @ExpectedSignature(descriptor = "(java.lang.Object, boolean)", signature = "(TT;Z)V") + ConstructorTest(T a, boolean b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, byte)", signature = "(TT;B)V") + ConstructorTest(T a, byte b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, char)", signature = "(TT;C)V") + ConstructorTest(T a, char b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, short)", signature = "(TT;S)V") + ConstructorTest(T a, short b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, int)", signature = "(TT;I)V") + ConstructorTest(T a, int b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, long)", signature = "(TT;J)V") + ConstructorTest(T a, long b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, float)", signature = "(TT;F)V") + ConstructorTest(T a, float b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, double)", signature = "(TT;D)V") + ConstructorTest(T a, double b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, java.lang.Runnable)", signature = "(TT;Ljava/lang/Runnable;)V") + ConstructorTest(T a, Runnable r) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, boolean[])", signature = "(TT;[Z)V") + ConstructorTest(T a, boolean[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, byte[])", signature = "(TT;[B)V") + ConstructorTest(T a, byte[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, char[])", signature = "(TT;[C)V") + ConstructorTest(T a, char[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, short[])", signature = "(TT;[S)V") + ConstructorTest(T a, short[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, int[])", signature = "(TT;[I)V") + ConstructorTest(T a, int[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, long[])", signature = "(TT;[J)V") + ConstructorTest(T a, long[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, float[])", signature = "(TT;[F)V") + ConstructorTest(T a, float[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, double[])", signature = "(TT;[D)V") + ConstructorTest(T a, double[] b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, java.lang.Runnable[])", signature = "(TT;[Ljava/lang/Runnable;)V") + ConstructorTest(T a, Runnable[] r) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object[])", signature = "([TT;)V") + ConstructorTest(T[] a) { + } + + @ExpectedSignature(descriptor = "(java.lang.Runnable[])", + signature = "([TT;)V") + ConstructorTest(T...a) { + } + + @ExpectedSignature(descriptor = "(java.util.Map)", signature = "(Ljava/util/Map<**>;)V") + ConstructorTest(Map a) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object)", signature = "(TT;)V") + ConstructorTest(T a) { + } + + @ExpectedSignature(descriptor = "(java.util.Set, java.util.Set)", + signature = ";>(TE;TE;)V") + > ConstructorTest(E a, E b) { + } + + @ExpectedSignature(descriptor = "(java.lang.ref.ReferenceQueue, java.lang.ref.ReferenceQueue)", + signature = ";:Ljava/util/Map<-TT;+TT;>;>(TE;TE;)V") + & Map> ConstructorTest(E a, E b) { + } + + @ExpectedSignature(descriptor = "(java.util.List)", signature = "(Ljava/util/List<+TT;>;)V") + ConstructorTest(List b) { + } + + @ExpectedSignature(descriptor = "(java.util.Set)", signature = "(Ljava/util/Set<-TT;>;)V") + ConstructorTest(Set b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Runnable)", signature = "(TE;)V") + ConstructorTest(E a) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, java.lang.Object)", signature = "(TT;TE;)V") + ConstructorTest(T a, E b) { + } + + // no Signature attribute + ConstructorTest(boolean b) { + } + + // no Signature attribute + ConstructorTest(HashMap a) { + } + + // no Signature attribute + ConstructorTest(boolean[] b) { + } + + // no Signature attribute + ConstructorTest(HashMap[] a) { + } +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/Driver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/Driver.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,239 @@ +/* + * 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 com.sun.tools.classfile.*; +import com.sun.tools.classfile.Field; +import com.sun.tools.classfile.Method; + +import java.io.File; +import java.io.FilenameFilter; +import java.lang.reflect.*; +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * The main class of Signature tests. + * Driver reads golden data of each class member that must have a Signature attribute, + * after that the class compares expected data with actual one. + * + * Example of usage Driver: + * java Driver Test + * + * Each member of the class Test should have @ExpectedSignature annotations + * if it must have the Signature attribute. Anonymous class cannot be annotated. + * So its enclosing class should be annotated and method isAnonymous + * of ExpectedSignature must return true. + */ +public class Driver extends TestResult { + + private final static String ACC_BRIDGE = "ACC_BRIDGE"; + + private final String topLevelClassName; + private final File[] files; + + public Driver(String topLevelClassName) { + this.topLevelClassName = topLevelClassName; + // Get top level class and all inner classes. + FilenameFilter filter = (dir, file) -> + file.equals(topLevelClassName + ".class") + || file.matches(topLevelClassName + "\\$.*\\.class"); + files = getClassDir().listFiles(filter); + } + + private boolean isAnonymous(String className) { + return className.matches(".*\\$\\d+$"); + } + + private Class getEnclosingClass(String className) throws ClassNotFoundException { + return Class.forName(className.replaceFirst("\\$\\d+$", "")); + } + + private ExpectedSignature getExpectedClassSignature(String className, Class clazz) + throws ClassNotFoundException { + // anonymous class cannot be annotated, so information about anonymous class + // is located in its enclosing class. + boolean isAnonymous = isAnonymous(className); + clazz = isAnonymous ? getEnclosingClass(className) : clazz; + return Stream.of(clazz.getAnnotationsByType(ExpectedSignature.class)) + .filter(s -> s.isAnonymous() == isAnonymous) + .collect(Collectors.toMap(ExpectedSignature::descriptor, Function.identity())) + .get(className); + } + + // Class.getName() cannot be used here, because the method can rely on signature attribute. + private Map getClassExpectedSignature(String className, Class clazz) + throws ClassNotFoundException { + Map classSignatures = new HashMap<>(); + ExpectedSignature classSignature = getExpectedClassSignature(className, clazz); + if (classSignature != null) { + classSignatures.put(className, classSignature); + } + return classSignatures; + } + + private Map getExpectedExecutableSignatures(Executable[] executables, + Predicate filterBridge) { + return Stream.of(executables) + .filter(filterBridge) + .map(e -> e.getAnnotation(ExpectedSignature.class)) + .filter(Objects::nonNull) + .collect(Collectors.toMap(ExpectedSignature::descriptor, Function.identity())); + } + + private Map getExpectedMethodSignatures(Class clazz) { + Map methodSignatures = + getExpectedExecutableSignatures(clazz.getDeclaredMethods(), + m -> !((java.lang.reflect.Method) m).isBridge()); + methodSignatures.putAll( + getExpectedExecutableSignatures(clazz.getDeclaredConstructors(), + m -> true)); + return methodSignatures; + } + + private Map getExpectedFieldSignatures(Class clazz) { + return Stream.of(clazz.getDeclaredFields()) + .map(f -> f.getAnnotation(ExpectedSignature.class)) + .filter(Objects::nonNull) + .collect(Collectors.toMap(ExpectedSignature::descriptor, Function.identity())); + } + + public void test() throws TestFailedException { + try { + addTestCase("Source is " + topLevelClassName + ".java"); + assertTrue(files.length > 0, "No class files found"); + for (File file : files) { + try { + String className = file.getName().replace(".class", ""); + Class clazz = Class.forName(className); + printf("Testing class %s\n", className); + ClassFile classFile = readClassFile(file); + + // test class signature + testAttribute( + className, + classFile, + () -> (Signature_attribute) classFile.getAttribute(Attribute.Signature), + getClassExpectedSignature(className, clazz).get(className)); + + testFields(getExpectedFieldSignatures(clazz), classFile); + + testMethods(getExpectedMethodSignatures(clazz), classFile); + } catch (Exception e) { + addFailure(e); + } + } + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + private void checkAllMembersFound(Set found, Map signatures, String message) { + if (signatures != null) { + checkContains(found, + signatures.values().stream() + .map(ExpectedSignature::descriptor) + .collect(Collectors.toSet()), + message); + } + } + + private void testMethods(Map expectedSignatures, ClassFile classFile) + throws ConstantPoolException, Descriptor.InvalidDescriptor { + String className = classFile.getName(); + Set foundMethods = new HashSet<>(); + for (Method method : classFile.methods) { + String methodName = getMethodName(classFile, method); + printf("Testing method %s\n", methodName); + if (method.access_flags.getMethodFlags().contains(ACC_BRIDGE)) { + printf("Bridge method is skipped : %s\n", methodName); + continue; + } + testAttribute( + methodName, + classFile, + () -> (Signature_attribute) method.attributes.get(Attribute.Signature), + expectedSignatures.get(methodName)); + foundMethods.add(methodName); + } + checkAllMembersFound(foundMethods, expectedSignatures, + "Checking that all methods of class " + className + " with Signature attribute found"); + } + + private String getMethodName(ClassFile classFile, Method method) + throws ConstantPoolException, Descriptor.InvalidDescriptor { + return String.format("%s%s", + method.getName(classFile.constant_pool), + method.descriptor.getParameterTypes(classFile.constant_pool)); + } + + private void testFields(Map expectedSignatures, ClassFile classFile) + throws ConstantPoolException { + String className = classFile.getName(); + Set foundFields = new HashSet<>(); + for (Field field : classFile.fields) { + String fieldName = field.getName(classFile.constant_pool); + printf("Testing field %s\n", fieldName); + testAttribute( + fieldName, + classFile, + () -> (Signature_attribute) field.attributes.get(Attribute.Signature), + expectedSignatures.get(fieldName)); + foundFields.add(fieldName); + } + checkAllMembersFound(foundFields, expectedSignatures, + "Checking that all fields of class " + className + " with Signature attribute found"); + } + + private void testAttribute( + String memberName, + ClassFile classFile, + Supplier sup, + ExpectedSignature expectedSignature) + throws ConstantPoolException { + + Signature_attribute attribute = sup.get(); + if (expectedSignature != null && checkNotNull(attribute, memberName + " must have attribute")) { + checkEquals(classFile.constant_pool.getUTF8Value(attribute.attribute_name_index), + "Signature", "Attribute's name : " + memberName); + checkEquals(attribute.attribute_length, 2, "Attribute's length : " + memberName); + checkEquals(attribute.getSignature(classFile.constant_pool), + expectedSignature.signature(), + "Testing signature of : " + memberName); + } else { + checkNull(attribute, memberName + " must not have attribute"); + } + } + + public static void main(String[] args) throws TestFailedException { + if (args.length != 1) { + throw new IllegalArgumentException("Usage: Driver "); + } + new Driver(args[0]).test(); + } +} \ No newline at end of file diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/EnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/EnumTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,39 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build EnumTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver EnumTest + */ + +@ExpectedSignature(descriptor = "EnumTest", signature = "Ljava/lang/Enum;") +public enum EnumTest {; + // see 8026480 + @ExpectedSignature(descriptor = "(java.lang.String, int)", signature = "()V") + private EnumTest() {} +} \ No newline at end of file diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/ExceptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ExceptionTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,98 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for methods which throw exceptions. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build ExceptionTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver ExceptionTest + */ + +import java.io.IOError; +import java.io.IOException; + +@ExpectedSignature(descriptor = "ExceptionTest", + signature = "Ljava/lang/Object;") +public class ExceptionTest { + + @ExpectedSignature(descriptor = "()", signature = "()V^TE;") + ExceptionTest() throws E { + } + + @ExpectedSignature(descriptor = "(int)", + signature = "(I)V^Ljava/io/IOException;^TE;^Ljava/io/IOError;") + ExceptionTest(int a) throws IOException, E, IOError { + } + + @ExpectedSignature(descriptor = "(long)", signature = "(J)V^TExc;") + ExceptionTest(long a) throws Exc { + } + + @ExpectedSignature(descriptor = "(byte)", signature = "(B)V^Ljava/io/IOError;^TExc;^Ljava/io/IOException;") + ExceptionTest(byte a) throws IOError, Exc, IOException { + } + + @ExpectedSignature(descriptor = "(java.lang.RuntimeException)", signature = "(TExc;)V") + ExceptionTest(Exc a) throws IOException { + } + + // no Signature attribute + ExceptionTest(String a) throws IOError { + } + + void noSignatureAttributeMethod() throws IOException { + } + + @ExpectedSignature(descriptor = "genericMethod(int)", signature = "(I)V^TExc;") + void genericMethod(int a) throws Exc { + } + + @ExpectedSignature(descriptor = "genericMethod(long)", signature = "(J)V^TExc;^Ljava/io/IOException;") + void genericMethod(long a) throws Exc, IOException { + } + + @ExpectedSignature(descriptor = "genericMethod(java.lang.RuntimeException)", signature = "(TExc;)V") + void genericMethod(Exc a) throws IOError { + } + + static void staticNoSignatureAttributeMethod() throws IOException { + } + + @ExpectedSignature(descriptor = "staticGenericMethod(int)", + signature = "(I)V^TE;") + static void staticGenericMethod(int a) throws E { + } + + @ExpectedSignature(descriptor = "staticGenericMethod(long)", + signature = "(J)V^Ljava/io/IOError;^TE;^Ljava/io/IOException;") + static void staticGenericMethod(long a) throws IOError, E, IOException { + } + + @ExpectedSignature(descriptor = "staticGenericMethod(java.lang.Exception)", + signature = "(TE;)V") + static void staticGenericMethod(E a) throws IOError { + } +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/ExpectedSignature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ExpectedSignature.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,34 @@ +/* + * 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.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Repeatable(ExpectedSignatureContainer.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpectedSignature { + boolean isAnonymous() default false; + String descriptor(); + String signature(); +} \ No newline at end of file diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/ExpectedSignatureContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ExpectedSignatureContainer.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,30 @@ +/* + * 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.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpectedSignatureContainer { + ExpectedSignature[] value(); +} \ No newline at end of file diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/FieldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/FieldTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8049238 + * @summary Checks Signature attribute for fields. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build FieldTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver FieldTest + */ + +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +@ExpectedSignature(descriptor = "FieldTest", signature = "Ljava/lang/Object;") +public class FieldTest { + + @ExpectedSignature(descriptor = "typeInList", signature = "Ljava/util/List;") + List typeInList; + + @ExpectedSignature(descriptor = "boundsType", signature = "Ljava/util/List;>;") + List> boundsType; + + @ExpectedSignature(descriptor = "type", signature = "TT;") + T type; + + @ExpectedSignature(descriptor = "typeInArray", signature = "[TT;") + T[] typeInArray; + + @ExpectedSignature(descriptor = "byteArrayInList", signature = "Ljava/util/List<[B>;") + List byteArrayInList; + + @ExpectedSignature(descriptor = "shortArrayInList", signature = "Ljava/util/List<[S>;") + List shortArrayInList; + + @ExpectedSignature(descriptor = "intArrayInList", signature = "Ljava/util/List<[I>;") + List intArrayInList; + + @ExpectedSignature(descriptor = "longArrayInList", signature = "Ljava/util/List<[J>;") + List longArrayInList; + + @ExpectedSignature(descriptor = "charArrayInList", signature = "Ljava/util/List<[C>;") + List charArrayInList; + + @ExpectedSignature(descriptor = "booleanArrayInList", signature = "Ljava/util/List<[Z>;") + List booleanArrayInList; + + @ExpectedSignature(descriptor = "floatArrayInList", signature = "Ljava/util/List<[F>;") + List floatArrayInList; + + @ExpectedSignature(descriptor = "doubleArrayInList", signature = "Ljava/util/List<[D>;") + List doubleArrayInList; + + @ExpectedSignature(descriptor = "integerInList", signature = "Ljava/util/List;") + List integerInList; + + @ExpectedSignature(descriptor = "typeInMultiArray", signature = "[[TT;") + T[][] typeInMultiArray; + + @ExpectedSignature(descriptor = "arrayOfClasses", signature = "[Ljava/util/List;") + List[] arrayOfClasses; + + @ExpectedSignature(descriptor = "extendsWildCard", signature = "Ljava/util/List<+TT;>;") + List extendsWildCard; + + @ExpectedSignature(descriptor = "superWildCard", signature = "Ljava/util/Comparator<-TT;>;") + Comparator superWildCard; + + @ExpectedSignature(descriptor = "extendsSuperWildCard", + signature = "Ljava/util/List<+Ljava/util/Comparator<-TT;>;>;") + List> extendsSuperWildCard; + + @ExpectedSignature(descriptor = "wildCard", signature = "Ljava/util/Comparator<*>;") + Comparator wildCard; + + @ExpectedSignature(descriptor = "boundsBooleanArray", signature = "Ljava/util/Map<+[Z-[Z>;") + Map boundsBooleanArray; + + @ExpectedSignature(descriptor = "boundsByteArray", signature = "Ljava/util/Map<+[B-[B>;") + Map boundsByteArray; + + @ExpectedSignature(descriptor = "boundsShortArray", signature = "Ljava/util/Map<+[S-[S>;") + Map boundsShortArray; + + @ExpectedSignature(descriptor = "boundsIntArray", signature = "Ljava/util/Map<+[I-[I>;") + Map boundsIntArray; + + @ExpectedSignature(descriptor = "boundsLongArray", signature = "Ljava/util/Map<+[J-[J>;") + Map boundsLongArray; + + @ExpectedSignature(descriptor = "boundsCharArray", signature = "Ljava/util/Map<+[C-[C>;") + Map boundsCharArray; + + @ExpectedSignature(descriptor = "boundsFloatArray", signature = "Ljava/util/Map<+[F-[F>;") + Map boundsFloatArray; + + @ExpectedSignature(descriptor = "boundsDoubleArray", signature = "Ljava/util/Map<+[D-[D>;") + Map boundsDoubleArray; + + @ExpectedSignature(descriptor = "boundsObjectArray", + signature = "Ljava/util/Map<+[Ljava/lang/Object;-[Ljava/lang/Object;>;") + Map boundsObjectArray; + + boolean booleanNoSignatureAttribute; + byte byteNoSignatureAttribute; + char charNoSignatureAttribute; + short shortNoSignatureAttribute; + int intNoSignatureAttribute; + long longNoSignatureAttribute; + float floatNoSignatureAttribute; + double doubleNoSignatureAttribute; + + List listNoSignatureAttribute; + + @ExpectedSignature(descriptor = "staticByteArrayInList", signature = "Ljava/util/List<[B>;") + static List staticByteArrayInList; + + @ExpectedSignature(descriptor = "staticShortArrayInList", signature = "Ljava/util/List<[S>;") + static List staticShortArrayInList; + + @ExpectedSignature(descriptor = "staticIntArrayInList", signature = "Ljava/util/List<[I>;") + static List staticIntArrayInList; + + @ExpectedSignature(descriptor = "staticLongArrayInList", signature = "Ljava/util/List<[J>;") + static List staticLongArrayInList; + + @ExpectedSignature(descriptor = "staticCharArrayInList", signature = "Ljava/util/List<[C>;") + static List staticCharArrayInList; + + @ExpectedSignature(descriptor = "staticBooleanArrayInList", signature = "Ljava/util/List<[Z>;") + static List staticBooleanArrayInList; + + @ExpectedSignature(descriptor = "staticFloatArrayInList", signature = "Ljava/util/List<[F>;") + static List staticFloatArrayInList; + + @ExpectedSignature(descriptor = "staticDoubleArrayInList", signature = "Ljava/util/List<[D>;") + static List staticDoubleArrayInList; + + @ExpectedSignature(descriptor = "staticIntegerInList", signature = "Ljava/util/List;") + static List staticIntegerInList; + + @ExpectedSignature(descriptor = "staticWildCard", signature = "Ljava/util/Comparator<*>;") + static Comparator staticWildCard; + + @ExpectedSignature(descriptor = "staticBoundsBooleanArray", signature = "Ljava/util/Map<+[Z-[Z>;") + static Map staticBoundsBooleanArray; + + @ExpectedSignature(descriptor = "staticBoundsByteArray", signature = "Ljava/util/Map<+[B-[B>;") + static Map staticBoundsByteArray; + + @ExpectedSignature(descriptor = "staticBoundsShortArray", signature = "Ljava/util/Map<+[S-[S>;") + static Map staticBoundsShortArray; + + @ExpectedSignature(descriptor = "staticBoundsIntArray", signature = "Ljava/util/Map<+[I-[I>;") + static Map staticBoundsIntArray; + + @ExpectedSignature(descriptor = "staticBoundsLongArray", signature = "Ljava/util/Map<+[J-[J>;") + static Map staticBoundsLongArray; + + @ExpectedSignature(descriptor = "staticBoundsCharArray", signature = "Ljava/util/Map<+[C-[C>;") + static Map staticBoundsCharArray; + + @ExpectedSignature(descriptor = "staticBoundsFloatArray", signature = "Ljava/util/Map<+[F-[F>;") + static Map staticBoundsFloatArray; + + @ExpectedSignature(descriptor = "staticBoundsDoubleArray", signature = "Ljava/util/Map<+[D-[D>;") + static Map staticBoundsDoubleArray; + + @ExpectedSignature(descriptor = "staticBoundsObjectArray", + signature = "Ljava/util/Map<+[Ljava/lang/Object;-[Ljava/lang/Object;>;") + static Map staticBoundsObjectArray; + + static boolean staticBooleanNoSignatureAttribute; + static byte staticByteNoSignatureAttribute; + static char staticCharNoSignatureAttribute; + static short staticShortNoSignatureAttribute; + static int staticIntNoSignatureAttribute; + static long staticLongNoSignatureAttribute; + static float staticFloatNoSignatureAttribute; + static double staticDoubleNoSignatureAttribute; + + static List staticListNoSignatureAttribute; +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/InnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/InnerClassTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,362 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for inner classes. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build InnerClassTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver InnerClassTest + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; + +@ExpectedSignature(descriptor = "InnerClassTest", + signature = ";:Ljava/lang/Runnable;>Ljava/lang/Object;") +@ExpectedSignature(descriptor = "InnerClassTest$1", + signature = "LInnerClassTest$1Local1;", isAnonymous = true) +@ExpectedSignature(descriptor = "InnerClassTest$2", + signature = "LInnerClassTest$1Local2;" + + "Ljava/util/Map;Ljava/util/ArrayList;>;>;", isAnonymous = true) +public class InnerClassTest & Runnable> { + + { + class Local1 { + // no Signature attribute + Local1() { + } + + @ExpectedSignature(descriptor = "genericType", signature = "TT;") + T genericType; + + @ExpectedSignature(descriptor = "genericTypeArray", signature = "[TT;") + T[] genericTypeArray; + } + + @ExpectedSignature(descriptor = "InnerClassTest$1Local2", + signature = ";>Ljava/lang/Object;") + class Local2> { + // no Signature attribute + Local2() { + } + + @ExpectedSignature(descriptor = "(InnerClassTest, java.lang.Object, java.util.Map)", + signature = "(TT;TU;)V") + Local2(T a, U b) { + } + + @ExpectedSignature(descriptor = "genericMethod(java.lang.Object[])", + signature = "([TT;)[TU;") + U[] genericMethod(T...a) { + return null; + } + } + + @ExpectedSignature(descriptor = "InnerClassTest$1Local3", + signature = "LInnerClassTest$1Local2;" + + "Ljava/util/Map;Ljava/util/ArrayList;>;>;") + class Local3 extends Local2, Map, ArrayList>> { + } + + new Local1() { + @ExpectedSignature(descriptor = "genericType", signature = "TT;") + T genericType; + + @ExpectedSignature(descriptor = "genericTypeArray", signature = "[TT;") + T[] genericTypeArray; + }; + + new Local2, Map, ArrayList>>() { + }; + } + + @ExpectedSignature(descriptor = "InnerClassTest$InnerClass1", + signature = ";>Ljava/lang/Object;") + class InnerClass1> { + @ExpectedSignature(descriptor = "genericTypeArray", signature = "[TT;") + T[] genericTypeArray; + + @ExpectedSignature(descriptor = "genericListExtendsBound", signature = "Ljava/util/List<+TT;>;") + List genericListExtendsBound; + + @ExpectedSignature(descriptor = "genericListSuperBound", signature = "Ljava/util/List<-TU;>;") + List genericListSuperBound; + + @ExpectedSignature(descriptor = "genericListWildCard", signature = "Ljava/util/List<*>;") + List genericListWildCard; + + @ExpectedSignature(descriptor = "genericListExactType", signature = "Ljava/util/List;") + List genericListExactType; + + @ExpectedSignature(descriptor = "listWithGenericType", signature = "Ljava/util/List;") + List listWithGenericType; + + List listNoSignatureAttribute; + + // no Signature attribute + InnerClass1(List a) { + } + + @ExpectedSignature(descriptor = "(InnerClassTest, java.util.ArrayList)", + signature = "(TT;)V") + InnerClass1(T a) { + } + + @ExpectedSignature(descriptor = "(InnerClassTest, java.util.ArrayList, java.util.ArrayList)", + signature = "(TT;TE;)V") + InnerClass1(T a, E b) { + } + + @ExpectedSignature(descriptor = "genericMethod(java.util.ArrayList)", + signature = "(TT;)TE;") + E genericMethod(T a) { + return null; + } + } + + @ExpectedSignature(descriptor = "InnerClassTest$InnerInterface", + signature = "Ljava/lang/Object;") + interface InnerInterface { + @ExpectedSignature(descriptor = "genericMethod(java.lang.Object)", signature = "(TT;)TT;") + T genericMethod(T a); + + @ExpectedSignature(descriptor = "genericListExtendsBound", signature = "Ljava/util/List<+Ljava/lang/Number;>;") + List genericListExtendsBound = null; + + @ExpectedSignature(descriptor = "genericListSuperBound", signature = "Ljava/util/List<-Ljava/lang/Number;>;") + List genericListSuperBound = null; + + @ExpectedSignature(descriptor = "genericListWildCard", signature = "Ljava/util/List<*>;") + List genericListWildCard = null; + + @ExpectedSignature(descriptor = "genericListExactType", signature = "Ljava/util/List;") + List genericListExactType = null; + + List listNoSignatureAttribute = null; + + @ExpectedSignature(descriptor = "genericBoundsMethod1(java.util.List)", + signature = "(Ljava/util/List<-TT;>;)Ljava/util/List<+TT;>;") + List genericBoundsMethod1(List a); + + @ExpectedSignature(descriptor = "genericBoundsMethod2(java.util.List)", + signature = "(Ljava/util/List<+TT;>;)Ljava/util/List<-TT;>;") + List genericBoundsMethod2(List a); + + @ExpectedSignature(descriptor = "genericWildCardMethod(java.util.Map)", + signature = "(Ljava/util/Map<**>;)Ljava/util/Map<**>;") + Map genericWildCardMethod(Map a); + + @ExpectedSignature(descriptor = "defaultGenericMethod(java.util.List, java.util.List, java.util.Map)", + signature = "(Ljava/util/List<+TT;>;Ljava/util/List<-TT;>;Ljava/util/Map<**>;)Ljava/util/List<*>;") + default List defaultGenericMethod(List list1, List list2, Map map) { return null; } + + + default List defaultNoSignatureAttributeMethod(List list1, List list2, Map list3) { return null; } + + @ExpectedSignature(descriptor = "staticGenericMethod(java.util.List, java.util.List, java.util.Map)", + signature = "(Ljava/util/List<+TT;>;Ljava/util/List<-TT;>;Ljava/util/Map<**>;)Ljava/util/List<*>;") + static List staticGenericMethod(List list1, List list2, Map map) { return null; } + + + static List staticNoSignatureAttributeMethod(List list1, List list2, Map list3) { return null; } + } + + @ExpectedSignature(descriptor = "InnerClassTest$InnerClass2", + signature = "LInnerClassTest.InnerClass1;>;LInnerClassTest$InnerInterface;") + class InnerClass2 extends InnerClass1> implements InnerInterface { + + // no Signature attribute + InnerClass2() { + super(null); + } + + @ExpectedSignature(descriptor = "(InnerClassTest, java.util.ArrayList)", + signature = "(TT;)V") + InnerClass2(T a) { + super(a); + } + + @ExpectedSignature(descriptor = "(InnerClassTest, java.util.ArrayList, java.util.ArrayList)", + signature = "(TT;TT;)V") + InnerClass2(T a, T b) { + super(a, b); + } + + @ExpectedSignature(descriptor = "genericMethod(java.util.ArrayList)", signature = "(TT;)TT;") + @Override + public T genericMethod(T a) { + return null; + } + + @ExpectedSignature(descriptor = "genericBoundsMethod1(java.util.List)", + signature = "(Ljava/util/List<-TT;>;)Ljava/util/List<+TT;>;") + @Override + public List genericBoundsMethod1(List a) { + return null; + } + + @ExpectedSignature(descriptor = "genericBoundsMethod2(java.util.List)", + signature = "(Ljava/util/List<+TT;>;)Ljava/util/List<-TT;>;") + @Override + public List genericBoundsMethod2(List a) { + return null; + } + + @ExpectedSignature(descriptor = "genericWildCardMethod(java.util.Map)", + signature = "(Ljava/util/Map<**>;)Ljava/util/Map<**>;") + @Override + public Map genericWildCardMethod(Map a) { + return null; + } + } + + @ExpectedSignature(descriptor = "InnerClassTest$StaticInnerClass", + signature = ";>" + + "Ljava/lang/Object;LInnerClassTest$InnerInterface;") + static class StaticInnerClass> implements InnerInterface { + // no Signature attribute + StaticInnerClass(List a) { + } + + @ExpectedSignature(descriptor = "(java.lang.Runnable)", + signature = "(TE;)V") + StaticInnerClass(E a) { + } + + @ExpectedSignature(descriptor = "(java.lang.String)", + signature = "(TT;)V") + StaticInnerClass(T a) { + } + + @ExpectedSignature(descriptor = "(java.lang.String, java.util.Set)", + signature = "(TT;TE;)V") + StaticInnerClass(T a, E b) { + } + + @ExpectedSignature(descriptor = "genericListExtendsBound", signature = "Ljava/util/List<+Ljava/lang/Number;>;") + static List genericListExtendsBound; + + @ExpectedSignature(descriptor = "genericListSuperBound", signature = "Ljava/util/List<-Ljava/lang/Number;>;") + static List genericListSuperBound; + + @ExpectedSignature(descriptor = "genericListWildCard", signature = "Ljava/util/List<*>;") + static List genericListWildCard; + + @ExpectedSignature(descriptor = "genericListExactType", signature = "Ljava/util/List;") + static List genericListExactType; + + static List listNoSignatureAttribute; + + @ExpectedSignature(descriptor = "genericMethod(java.util.Set)", + signature = "(TE;)TE;") + @Override + public E genericMethod(E a) { + return null; + } + + @ExpectedSignature(descriptor = "genericBoundsMethod1(java.util.List)", + signature = "(Ljava/util/List<-TE;>;)Ljava/util/List<+TE;>;") + @Override + public List genericBoundsMethod1(List a) { + return null; + } + + @ExpectedSignature(descriptor = "genericBoundsMethod2(java.util.List)", + signature = "(Ljava/util/List<+TE;>;)Ljava/util/List<-TE;>;") + @Override + public List genericBoundsMethod2(List a) { + return null; + } + + @ExpectedSignature(descriptor = "genericWildCardMethod(java.util.Map)", + signature = "(Ljava/util/Map<**>;)Ljava/util/Map<**>;") + @Override + public Map genericWildCardMethod(Map a) { + return null; + } + + @ExpectedSignature(descriptor = "staticGenericMethod(java.lang.Object)", + signature = "(TE;)TE;") + public static E staticGenericMethod(E a) { + return null; + } + + @ExpectedSignature(descriptor = "staticGenericBoundsMethod1(java.util.List)", + signature = "(Ljava/util/List<-TE;>;)Ljava/util/List<+TE;>;") + public static List staticGenericBoundsMethod1(List a) { + return null; + } + + @ExpectedSignature(descriptor = "staticGenericBoundsMethod2(java.util.List)", + signature = "(Ljava/util/List<+TE;>;)Ljava/util/List<-TE;>;") + public static List staticGenericBoundsMethod2(List a) { + return null; + } + + @ExpectedSignature(descriptor = "staticGenericWildCardMethod(java.util.Map)", + signature = "(Ljava/util/Map<**>;)Ljava/util/Map<**>;") + public static Map staticGenericWildCardMethod(Map a) { + return null; + } + } + + @ExpectedSignature(descriptor = "InnerClassTest$InnerClass3", + signature = "Ljava/lang/Object;LInnerClassTest$ExceptionHolder" + + ";Ljava/util/concurrent/Callable;>;") + public static class InnerClass3 implements ExceptionHolder, Callable> { + @ExpectedSignature(descriptor = "call()", signature = "()Ljava/util/Map<**>;") + @Override + public Map call() throws Exception { + return null; + } + + @Override + public void Throw() throws RuntimeException { + } + + @Override + public RuntimeException Return() { + return null; + } + } + + /** + * Class is for checking that the Signature attribute is not generated + * for overridden methods despite of the appropriate methods in the parent class + * have the Signature attribute. + */ + @ExpectedSignature(descriptor = "InnerClassTest$ExceptionHolder", + signature = "Ljava/lang/Object;") + interface ExceptionHolder { + @ExpectedSignature(descriptor = "Throw()", signature = "()V^TE;") + void Throw() throws E; + @ExpectedSignature(descriptor = "Return()", signature = "()TE;") + E Return(); + } +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/MethodParameterTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/MethodParameterTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,203 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for method parameters. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build MethodParameterTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver MethodParameterTest + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@ExpectedSignature(descriptor = "MethodParameterTest", signature = "Ljava/lang/Object;") +public class MethodParameterTest { + + @ExpectedSignature(descriptor = "(java.lang.Object, java.util.Set, java.util.ArrayList)", + signature = ";:Ljava/lang/Runnable;>" + + "(TT;Ljava/util/Set<-TE;>;Ljava/util/ArrayList<+Ljava/util/Set;>;)V") + & Runnable> + MethodParameterTest(T a, Set b, ArrayList> c) { + } + + @ExpectedSignature(descriptor = "method(java.lang.Object, java.util.List, java.util.ArrayList)", + signature = ";:Ljava/lang/Runnable;>" + + "(TT;TU;Ljava/util/ArrayList<+Ljava/util/Set;>;)V") + & Runnable> + void method(T a, U b, ArrayList> c) { + } + + @ExpectedSignature(descriptor = "staticMethod(java.util.Set, java.util.List[], java.util.Map)", + signature = ";E::Ljava/util/Set<-TT;>;>(TE;[TT;Ljava/util/Map<*+TE;>;)TE;") + static , E extends Set> E staticMethod(E a, T[] b, Map c) { + return null; + } + + @ExpectedSignature(descriptor = "(java.lang.Object, boolean[])", signature = "(TT;[Z)V") + MethodParameterTest(T a, boolean...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, char[])", signature = "(TT;[C)V") + MethodParameterTest(T a, char...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, byte[])", signature = "(TT;[B)V") + MethodParameterTest(T a, byte...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, short[])", signature = "(TT;[S)V") + MethodParameterTest(T a, short...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, int[])", signature = "(TT;[I)V") + MethodParameterTest(T a, int...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, long[])", signature = "(TT;[J)V") + MethodParameterTest(T a, long...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, float[])", signature = "(TT;[F)V") + MethodParameterTest(T a, float...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, double[])", signature = "(TT;[D)V") + MethodParameterTest(T a, double...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object, java.lang.Object[])", + signature = "(TT;[Ljava/lang/Object;)V") + MethodParameterTest(T a, Object...b) { + } + + @ExpectedSignature(descriptor = "(java.lang.Object[])", signature = "([TT;)V") + MethodParameterTest(T...a) { + } + + // no Signature attribute + MethodParameterTest(int...a) { + } + + @ExpectedSignature(descriptor = "genericBooleanMethod(java.lang.Object, boolean[])", signature = "(TT;[Z)V") + void genericBooleanMethod(T a, boolean...b) { + } + + @ExpectedSignature(descriptor = "genericCharMethod(java.lang.Object, char[])", signature = "(TT;[C)V") + void genericCharMethod(T a, char...b) { + } + + @ExpectedSignature(descriptor = "genericByteMethod(java.lang.Object, byte[])", signature = "(TT;[B)V") + void genericByteMethod(T a, byte...b) { + } + + @ExpectedSignature(descriptor = "genericShortMethod(java.lang.Object, short[])", signature = "(TT;[S)V") + void genericShortMethod(T a, short...b) { + } + + @ExpectedSignature(descriptor = "genericIntMethod(java.lang.Object, int[])", signature = "(TT;[I)V") + void genericIntMethod(T a, int...b) { + } + + @ExpectedSignature(descriptor = "genericLongMethod(java.lang.Object, long[])", signature = "(TT;[J)V") + void genericLongMethod(T a, long...b) { + } + + @ExpectedSignature(descriptor = "genericFloatMethod(java.lang.Object, float[])", signature = "(TT;[F)V") + void genericFloatMethod(T a, float...b) { + } + + @ExpectedSignature(descriptor = "genericDoubleMethod(java.lang.Object, double[])", signature = "(TT;[D)V") + void genericDoubleMethod(T a, double...b) { + } + + @ExpectedSignature(descriptor = "genericObjectMethod(java.lang.Object, java.lang.Object[])", + signature = "(TT;[Ljava/lang/Object;)V") + void genericObjectMethod(T a, Object...b) { + } + + @ExpectedSignature(descriptor = "genericMethod(java.lang.Object[])", signature = "([TT;)V") + void genericMethod(T...a) { + } + + void noSignature(int...a) { + } + + @ExpectedSignature(descriptor = "staticGenericBooleanMethod(java.lang.Object, boolean[])", + signature = "(TT;[Z)V") + static void staticGenericBooleanMethod(T a, boolean...b) { + } + + @ExpectedSignature(descriptor = "staticGenericCharMethod(java.lang.Object, char[])", + signature = "(TT;[C)V") + static void staticGenericCharMethod(T a, char...b) { + } + + @ExpectedSignature(descriptor = "staticGenericByteMethod(java.lang.Object, byte[])", + signature = "(TT;[B)V") + static void staticGenericByteMethod(T a, byte...b) { + } + + @ExpectedSignature(descriptor = "staticGenericShortMethod(java.lang.Object, short[])", + signature = "(TT;[S)V") + static void staticGenericShortMethod(T a, short...b) { + } + + @ExpectedSignature(descriptor = "staticGenericIntMethod(java.lang.Object, int[])", + signature = "(TT;[I)V") + static void staticGenericIntMethod(T a, int...b) { + } + + @ExpectedSignature(descriptor = "staticGenericLongMethod(java.lang.Object, long[])", + signature = "(TT;[J)V") + static void staticGenericLongMethod(T a, long...b) { + } + + @ExpectedSignature(descriptor = "staticGenericFloatMethod(java.lang.Object, float[])", + signature = "(TT;[F)V") + static void staticGenericFloatMethod(T a, float...b) { + } + + @ExpectedSignature(descriptor = "staticGenericDoubleMethod(java.lang.Object, double[])", + signature = "(TT;[D)V") + static void staticGenericDoubleMethod(T a, double...b) { + } + + @ExpectedSignature(descriptor = "staticGenericObjectMethod(java.lang.Object, java.lang.Object[])", + signature = "(TT;[Ljava/lang/Object;)V") + static void staticGenericObjectMethod(T a, Object...b) { + } + + @ExpectedSignature(descriptor = "staticGenericMethod(java.lang.Object[])", + signature = "([TT;)V") + static void staticGenericMethod(T...a) { + } + + static void staticNoSignatureAttribute(int...a) { + } +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/MethodTypeBoundTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/MethodTypeBoundTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,79 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for type bounds. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build MethodTypeBoundTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver MethodTypeBoundTest + */ + +import java.util.*; + +@ExpectedSignature(descriptor = "MethodTypeBoundTest", signature = "Ljava/lang/Object;") +public class MethodTypeBoundTest { + + @ExpectedSignature(descriptor = "method1(java.lang.String)", + signature = ";>(TE;)TE;") + > E method1(E a) { + return a; + } + + @ExpectedSignature(descriptor = "method2(java.lang.Runnable)", + signature = ";>(TE;)TE;") + > E method2(E a) { + return a; + } + + @ExpectedSignature(descriptor = "method3(java.util.ArrayList)", + signature = ";>(TE;)TE;") + > E method3(E a) { + return a; + } + + @ExpectedSignature(descriptor = "method4(java.util.LinkedList)", + signature = ";:Ljava/util/List;>(TE;)TE;") + & List> E method4(E a) { + return a; + } + + @ExpectedSignature(descriptor = "method5(java.util.Iterator)", + signature = ";:Ljava/util/List;" + + "U::Ljava/util/Iterator<-LMethodTypeBoundTest.InnerClass;>;>(TU;)TE;") + & List, U extends Iterator>> E method5(U a) { + return null; + } + + @ExpectedSignature(descriptor = "method6()", + signature = ";U:TE;>()V") + , U extends E> void method6() { + } + + @ExpectedSignature(descriptor = "MethodTypeBoundTest$InnerClass", + signature = "Ljava/lang/Object;") + class InnerClass { + } +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/Signature/ReturnTypeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ReturnTypeTest.java Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,549 @@ +/* + * 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 8049238 + * @summary Checks Signature attribute for array return type of method. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @build ReturnTypeTest Driver ExpectedSignature ExpectedSignatureContainer + * @run main Driver ReturnTypeTest + */ + +import java.awt.Frame; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +@ExpectedSignature(descriptor = "ReturnTypeTest", + signature = ";>Ljava/lang/Object;") +public class ReturnTypeTest> { + + @ExpectedSignature(descriptor = "byteArrayReturnType(java.awt.Frame)", + signature = "(TT;)[B") + byte[] byteArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "shortArrayReturnType(java.awt.Frame)", + signature = "(TT;)[S") + short[] shortArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "charArrayReturnType(java.awt.Frame)", + signature = "(TT;)[C") + char[] charArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "intArrayReturnType(java.awt.Frame)", + signature = "(TT;)[I") + int[] intArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "longArrayReturnType(java.awt.Frame)", + signature = "(TT;)[J") + long[] longArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "booleanArrayReturnType(java.awt.Frame)", + signature = "(TT;)[Z") + boolean[] booleanArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "floatArrayReturnType(java.awt.Frame)", + signature = "(TT;)[F") + float[] floatArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "doubleArrayReturnType(java.awt.Frame)", + signature = "(TT;)[D") + double[] doubleArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "objectArrayReturnType(java.awt.Frame)", + signature = "(TT;)[Ljava/lang/Object;") + Object[] objectArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticByteArrayReturnType(java.lang.Object)", + signature = "(TT;)[B") + static byte[] staticByteArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticShortArrayReturnType(java.lang.Object)", + signature = "(TT;)[S") + static short[] staticShortArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticCharArrayReturnType(java.lang.Object)", + signature = "(TT;)[C") + static char[] staticCharArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticIntArrayReturnType(java.lang.Object)", + signature = "(TT;)[I") + static int[] staticIntArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticLongArrayReturnType(java.lang.Object)", + signature = "(TT;)[J") + static long[] staticLongArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticBooleanArrayReturnType(java.lang.Object)", + signature = "(TT;)[Z") + static boolean[] staticBooleanArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticFloatArrayReturnType(java.lang.Object)", + signature = "(TT;)[F") + static float[] staticFloatArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticDoubleArrayReturnType(java.lang.Object)", + signature = "(TT;)[D") + static double[] staticDoubleArrayReturnType(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticObjectArrayReturnType(java.lang.Object)", + signature = "(TT;)[Ljava/lang/Object;") + static Object[] staticObjectArrayReturnType(T a) { + return null; + } + + byte[] byteArrayReturnTypeNoSignatureAttribute() { + return null; + } + + short[] shortArrayReturnTypeNoSignatureAttribute() { + return null; + } + + char[] charArrayReturnTypeNoSignatureAttribute() { + return null; + } + + int[] intArrayReturnTypeNoSignatureAttribute() { + return null; + } + + long[] longArrayReturnTypeNoSignatureAttribute() { + return null; + } + + boolean[] booleanArrayReturnTypeNoSignatureAttribute() { + return null; + } + + float[] floatArrayReturnTypeNoSignatureAttribute() { + return null; + } + + double[] doubleArrayReturnTypeNoSignatureAttribute() { + return null; + } + + Object[] objectArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static byte[] staticByteArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static short[] staticShortArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static char[] staticCharArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static int[] staticIntArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static long[] staticLongArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static boolean[] staticBooleanArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static float[] staticFloatArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static double[] staticDoubleArrayReturnTypeNoSignatureAttribute() { + return null; + } + + static Object[] staticObjectArrayReturnTypeNoSignatureAttribute() { + return null; + } + + @ExpectedSignature(descriptor = "typeReturnType()", + signature = "()TT;") + T typeReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "typeArrayReturnType()", + signature = "()[TT;") + T[] typeArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "extendsReturnType()", + signature = "()TE;") + E extendsReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "extendsArrayReturnType()", + signature = "()[TE;") + E[] extendsArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "genericListReturnType()", + signature = "()Ljava/util/List;") + List genericListReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "genericListArrayReturnType()", + signature = "()[Ljava/util/List;") + List[] genericListArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "extendsBoundReturnType()", + signature = "()Ljava/util/List<+TT;>;") + List extendsBoundReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "extendsBoundArrayReturnType()", + signature = "()[Ljava/util/List<+TT;>;") + List[] extendsBoundArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "superBoundReturnType()", + signature = "()Ljava/util/List<-TT;>;") + List superBoundReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "superBoundArrayReturnType()", + signature = "()[Ljava/util/List<-TT;>;") + List[] superBoundArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "wildcardReturnType()", + signature = "()Ljava/util/Map<**>;") + Map wildcardReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "wildcardArrayReturnType()", + signature = "()[Ljava/util/Map<**>;") + Map[] wildcardArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticTypeReturnType()", + signature = "()TT;") + static T staticTypeReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticTypeArrayReturnType()", + signature = "()[TT;") + static T[] staticTypeArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticExtendsReturnType()", + signature = "()TE;") + static E staticExtendsReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticExtendsArrayReturnType()", + signature = "()[TE;") + static E[] staticExtendsArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticGenericListReturnType()", + signature = "()Ljava/util/List;") + static List staticGenericListReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticGenericListArrayReturnType()", + signature = "()[Ljava/util/List;") + static List[] staticGenericListArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticExtendsBoundReturnType()", + signature = "()Ljava/util/List<+TT;>;") + static List staticExtendsBoundReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticExtendsBoundArrayReturnType()", + signature = "()[Ljava/util/List<+TT;>;") + static List[] staticExtendsBoundArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticSuperBoundReturnType()", + signature = "()Ljava/util/List<-TT;>;") + static List staticSuperBoundReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticSuperBoundArrayReturnType()", + signature = "()[Ljava/util/List<-TT;>;") + static List[] staticSuperBoundArrayReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticWildcardReturnType()", + signature = "()Ljava/util/Map<**>;") + static Map staticWildcardReturnType() { + return null; + } + + @ExpectedSignature(descriptor = "staticWildcardArrayReturnType()", + signature = "()[Ljava/util/Map<**>;") + static Map[] staticWildcardArrayReturnType() { + return null; + } + + List noSignature() { + return null; + } + + static List staticNoSignatureAttribute() { + return null; + } + + @ExpectedSignature(descriptor = "boundsBooleanArray()", + signature = "()Ljava/util/Map<+[Z-[Z>;") + Map boundsBooleanArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsByteArray()", + signature = "()Ljava/util/Map<+[B-[B>;") + Map boundsByteArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsShortArray()", + signature = "()Ljava/util/Map<+[S-[S>;") + Map boundsShortArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsIntArray()", + signature = "()Ljava/util/Map<+[I-[I>;") + Map boundsIntArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsLongArray()", + signature = "()Ljava/util/Map<+[J-[J>;") + Map boundsLongArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsCharArray()", + signature = "()Ljava/util/Map<+[C-[C>;") + Map boundsCharArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsFloatArray()", + signature = "()Ljava/util/Map<+[F-[F>;") + Map boundsFloatArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsDoubleArray()", + signature = "()Ljava/util/Map<+[D-[D>;") + Map boundsDoubleArray() { + return null; + } + + @ExpectedSignature(descriptor = "boundsObjectArray()", + signature = "()Ljava/util/Map<+[Ljava/lang/Object;-[Ljava/lang/Object;>;") + Map boundsObjectArray() { + return null; + } + + @ExpectedSignature(descriptor = "voidMethod(java.awt.Frame)", signature = "(TT;)V") + void voidMethod(T a) { + } + + @ExpectedSignature(descriptor = "byteMethod(java.awt.Frame)", signature = "(TT;)B") + byte byteMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "shortMethod(java.awt.Frame)", signature = "(TT;)S") + short shortMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "charMethod(java.awt.Frame)", signature = "(TT;)C") + char charMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "intMethod(java.awt.Frame)", signature = "(TT;)I") + int intMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "longMethod(java.awt.Frame)", signature = "(TT;)J") + long longMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "booleanMethod(java.awt.Frame)", signature = "(TT;)Z") + boolean booleanMethod(T a) { + return false; + } + + @ExpectedSignature(descriptor = "floatMethod(java.awt.Frame)", signature = "(TT;)F") + float floatMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "doubleMethod(java.awt.Frame)", signature = "(TT;)D") + double doubleMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "objectMethod(java.awt.Frame)", signature = "(TT;)Ljava/lang/Object;") + Object objectMethod(T a) { + return null; + } + + @ExpectedSignature(descriptor = "staticVoidMethod(java.lang.Object)", signature = "(TT;)V") + static void staticVoidMethod(T a) { + } + + @ExpectedSignature(descriptor = "staticByteMethod(java.lang.Object)", signature = "(TT;)B") + static byte staticByteMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticShortMethod(java.lang.Object)", signature = "(TT;)S") + static short staticShortMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticCharMethod(java.lang.Object)", signature = "(TT;)C") + static char staticCharMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticIntMethod(java.lang.Object)", signature = "(TT;)I") + static int staticIntMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticLongMethod(java.lang.Object)", signature = "(TT;)J") + static long staticLongMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticBooleanMethod(java.lang.Object)", signature = "(TT;)Z") + static boolean staticBooleanMethod(T a) { + return false; + } + + @ExpectedSignature(descriptor = "staticFloatMethod(java.lang.Object)", signature = "(TT;)F") + static float staticFloatMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticDoubleMethod(java.lang.Object)", signature = "(TT;)D") + static double staticDoubleMethod(T a) { + return 0; + } + + @ExpectedSignature(descriptor = "staticObjectMethod(java.lang.Object)", + signature = "(TT;)Ljava/lang/Object;") + static Object staticObjectMethod(T a) { + return null; + } + + void voidReturnTypeNoSignatureAttribute() { + } + + byte byteReturnTypeNoSignatureAttribute() { + return 0; + } + + Object objectReturnNoSignatureAttribute() { + return null; + } + + static void staticVoidReturnTypeNoSignatureAttribute() { + } + + static byte staticByteReturnTypeNoSignatureAttribute() { + return 0; + } + + static Object staticObjectReturnTypeNoSignatureAttribute() { + return null; + } +} diff -r d47c58140b41 -r 427f83353f73 langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Tue Mar 31 16:22:59 2015 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Mon Apr 06 10:35:43 2015 -0700 @@ -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 @@ -56,8 +56,9 @@ public boolean checkEquals(Object actual, Object expected, String message) { echo("Testing : " + message); if (!Objects.equals(actual, expected)) { - getLastTestCase().addAssert(new AssertionFailedException( - String.format("%s%nGot: %s, Expected: %s", message, actual, expected))); + getLastTestCase().addAssert(String.format("%s\n" + + "Expected: %s,\n" + + " Got: %s", message, expected, actual)); return false; } return true; @@ -70,8 +71,7 @@ public boolean checkNotNull(Object actual, String message) { echo("Testing : " + message); if (Objects.isNull(actual)) { - getLastTestCase().addAssert(new AssertionFailedException( - message + " : Expected not null value")); + getLastTestCase().addAssert(message + " : Expected not null value"); return false; } return true; @@ -88,7 +88,11 @@ public boolean checkContains(Set found, Set expected, String message) { Set copy = new HashSet<>(expected); copy.removeAll(found); - return checkTrue(found.containsAll(expected), message + " : " + copy); + if (!found.containsAll(expected)) { + return checkTrue(false, message + " FAIL : not found elements : " + copy); + } else { + return checkTrue(true, message + " PASS : all elements found"); + } } public void addFailure(Throwable th) { @@ -119,7 +123,7 @@ private class Info { private final String info; - private final List asserts; + private final List asserts; private final List errors; private Info(String info) { @@ -141,19 +145,25 @@ printf("[ERROR] : %s\n", getStackTrace(th)); } - public void addAssert(AssertionFailedException e) { + public void addAssert(String e) { asserts.add(e); - printf("[ASSERT] : %s\n", getStackTrace(e)); + printf("[ASSERT] : %s\n", e); } public String getMessage() { - return (asserts.size() > 0 ? getErrorMessage("[ASSERT]", asserts) + "\n" : "") - + getErrorMessage("[ERROR]", errors); + return (asserts.size() > 0 ? getAssertMessages(asserts) + "\n" : "") + + getErrorMessages(errors); } - public String getErrorMessage(String header, List list) { + public String getAssertMessages(List list) { return list.stream() - .map(throwable -> String.format("%s : %s", header, getStackTrace(throwable))) + .map(message -> String.format("[ASSERT] : %s", message)) + .collect(Collectors.joining("\n")); + } + + public String getErrorMessages(List list) { + return list.stream() + .map(throwable -> String.format("[ERROR] : %s", getStackTrace(throwable))) .collect(Collectors.joining("\n")); } diff -r d47c58140b41 -r 427f83353f73 make/jprt.properties --- a/make/jprt.properties Tue Mar 31 16:22:59 2015 -0700 +++ b/make/jprt.properties Mon Apr 06 10:35:43 2015 -0700 @@ -119,6 +119,12 @@ ${my.i586.default.build.configure.args} \ ${jprt.productOpen.build.configure.args} +jprt.windows_i586_6.2.build.configure.args= \ + --with-toolchain-version=2013 \ + ${jprt.i586.build.configure.args} +jprt.windows_x64_6.2.build.configure.args= \ + --with-toolchain-version=2013 + ######## # # Build targets and options (default/jdk) @@ -134,8 +140,8 @@ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ macosx_x64_10.9-{product|fastdebug}, \ - windows_i586_6.1-{product|fastdebug}, \ - windows_x64_6.1-{product|fastdebug} + windows_i586_6.2-{product|fastdebug}, \ + windows_x64_6.2-{product|fastdebug} # Test target list (no fastdebug & limited c2 testing) my.test.target.set= \ @@ -144,8 +150,8 @@ linux_i586_2.6-product-{c1|c2}-TESTNAME, \ linux_x64_2.6-product-c2-TESTNAME, \ macosx_x64_10.9-product-c2-TESTNAME, \ - windows_i586_6.1-product-c1-TESTNAME, \ - windows_x64_6.1-product-c2-TESTNAME + windows_i586_6.2-product-c1-TESTNAME, \ + windows_x64_6.2-product-c2-TESTNAME # Default vm test targets (testset=default) my.test.targets.default= \ @@ -256,8 +262,8 @@ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ macosx_x64_10.9-{product|fastdebug}, \ - windows_i586_6.1-{product|fastdebug}, \ - windows_x64_6.1-{product|fastdebug}, \ + windows_i586_6.2-{product|fastdebug}, \ + windows_x64_6.2-{product|fastdebug}, \ solaris_x64_5.11-{debugOpen}, \ linux_x64_2.6-{productOpen}, \ ${my.additional.build.targets.hotspot} @@ -346,43 +352,43 @@ macosx_x64_10.9-{product|fastdebug}-c2-jbb_ParOldGC my.test.targets.hotspot.windows.i586= \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-jvm98, \ - windows_i586_6.1-{product|fastdebug}-c2-jvm98_nontiered, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-scimark, \ - windows_i586_6.1-product-{c1|c2}-runThese8, \ - windows_i586_6.1-product-{c1|c2}-runThese8_Xcomp_lang, \ - windows_i586_6.1-product-{c1|c2}-runThese8_Xcomp_vm, \ - windows_i586_6.1-fastdebug-c1-runThese8_Xshare, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ - windows_i586_6.1-{product|fastdebug}-{c1|c2}-jbb_default, \ - windows_i586_6.1-{product|fastdebug}-c2-jbb_default_nontiered, \ - windows_i586_6.1-product-{c1|c2}-jbb_ParallelGC, \ - windows_i586_6.1-product-{c1|c2}-jbb_CMS, \ - windows_i586_6.1-product-{c1|c2}-jbb_G1, \ - windows_i586_6.1-product-{c1|c2}-jbb_ParOldGC + windows_i586_6.2-{product|fastdebug}-{c1|c2}-jvm98, \ + windows_i586_6.2-{product|fastdebug}-c2-jvm98_nontiered, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-scimark, \ + windows_i586_6.2-product-{c1|c2}-runThese8, \ + windows_i586_6.2-product-{c1|c2}-runThese8_Xcomp_lang, \ + windows_i586_6.2-product-{c1|c2}-runThese8_Xcomp_vm, \ + windows_i586_6.2-fastdebug-c1-runThese8_Xshare, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ + windows_i586_6.2-{product|fastdebug}-{c1|c2}-jbb_default, \ + windows_i586_6.2-{product|fastdebug}-c2-jbb_default_nontiered, \ + windows_i586_6.2-product-{c1|c2}-jbb_ParallelGC, \ + windows_i586_6.2-product-{c1|c2}-jbb_CMS, \ + windows_i586_6.2-product-{c1|c2}-jbb_G1, \ + windows_i586_6.2-product-{c1|c2}-jbb_ParOldGC my.test.targets.hotspot.windows.x64= \ - windows_x64_6.1-{product|fastdebug}-c2-jvm98, \ - windows_x64_6.1-{product|fastdebug}-c2-jvm98_nontiered, \ - windows_x64_6.1-{product|fastdebug}-c2-scimark, \ - windows_x64_6.1-product-c2-runThese8, \ - windows_x64_6.1-product-c2-runThese8_Xcomp_lang, \ - windows_x64_6.1-product-c2-runThese8_Xcomp_vm, \ - windows_x64_6.1-{product|fastdebug}-c2-GCBasher_SerialGC, \ - windows_x64_6.1-{product|fastdebug}-c2-GCBasher_ParallelGC, \ - windows_x64_6.1-{product|fastdebug}-c2-GCBasher_CMS, \ - windows_x64_6.1-{product|fastdebug}-c2-GCBasher_G1, \ - windows_x64_6.1-{product|fastdebug}-c2-GCBasher_ParOldGC, \ - windows_x64_6.1-{product|fastdebug}-c2-jbb_default, \ - windows_x64_6.1-{product|fastdebug}-c2-jbb_default_nontiered, \ - windows_x64_6.1-product-c2-jbb_CMS, \ - windows_x64_6.1-product-c2-jbb_ParallelGC, \ - windows_x64_6.1-product-c2-jbb_G1, \ - windows_x64_6.1-product-c2-jbb_ParOldGC + windows_x64_6.2-{product|fastdebug}-c2-jvm98, \ + windows_x64_6.2-{product|fastdebug}-c2-jvm98_nontiered, \ + windows_x64_6.2-{product|fastdebug}-c2-scimark, \ + windows_x64_6.2-product-c2-runThese8, \ + windows_x64_6.2-product-c2-runThese8_Xcomp_lang, \ + windows_x64_6.2-product-c2-runThese8_Xcomp_vm, \ + windows_x64_6.2-{product|fastdebug}-c2-GCBasher_SerialGC, \ + windows_x64_6.2-{product|fastdebug}-c2-GCBasher_ParallelGC, \ + windows_x64_6.2-{product|fastdebug}-c2-GCBasher_CMS, \ + windows_x64_6.2-{product|fastdebug}-c2-GCBasher_G1, \ + windows_x64_6.2-{product|fastdebug}-c2-GCBasher_ParOldGC, \ + windows_x64_6.2-{product|fastdebug}-c2-jbb_default, \ + windows_x64_6.2-{product|fastdebug}-c2-jbb_default_nontiered, \ + windows_x64_6.2-product-c2-jbb_CMS, \ + windows_x64_6.2-product-c2-jbb_ParallelGC, \ + windows_x64_6.2-product-c2-jbb_G1, \ + windows_x64_6.2-product-c2-jbb_ParOldGC # Some basic "smoke" tests for OpenJDK builds my.test.targets.hotspot.open= \ @@ -411,7 +417,7 @@ my.make.rule.test.targets.hotspot.clienttests= \ linux_i586_2.6-*-c1-hotspot_clienttest, \ - windows_i586_6.1-*-c1-hotspot_clienttest + windows_i586_6.2-*-c1-hotspot_clienttest my.make.rule.test.targets.hotspot.servertests= \ solaris_sparcv9_5.11-*-c2-hotspot_servertest, \ @@ -419,8 +425,8 @@ linux_i586_2.6-*-c2-hotspot_servertest, \ linux_x64_2.6-*-c2-hotspot_servertest, \ macosx_x64_10.9-*-c2-hotspot_servertest, \ - windows_i586_6.1-*-c2-hotspot_servertest, \ - windows_x64_6.1-*-c2-hotspot_servertest + windows_i586_6.2-*-c2-hotspot_servertest, \ + windows_x64_6.2-*-c2-hotspot_servertest my.make.rule.test.targets.hotspot.internalvmtests= \ solaris_sparcv9_5.11-fastdebug-c2-hotspot_internalvmtests, \ @@ -428,8 +434,8 @@ linux_i586_2.6-fastdebug-c2-hotspot_internalvmtests, \ linux_x64_2.6-fastdebug-c2-hotspot_internalvmtests, \ macosx_x64_10.9-fastdebug-c2-hotspot_internalvmtests, \ - windows_i586_6.1-fastdebug-c2-hotspot_internalvmtests, \ - windows_x64_6.1-fastdebug-c2-hotspot_internalvmtests + windows_i586_6.2-fastdebug-c2-hotspot_internalvmtests, \ + windows_x64_6.2-fastdebug-c2-hotspot_internalvmtests my.make.rule.test.targets.hotspot.reg.group= \ solaris_sparcv9_5.11-fastdebug-c2-GROUP, \ @@ -437,10 +443,10 @@ linux_i586_2.6-fastdebug-c2-GROUP, \ linux_x64_2.6-fastdebug-c2-GROUP, \ macosx_x64_10.9-fastdebug-c2-GROUP, \ - windows_i586_6.1-fastdebug-c2-GROUP, \ - windows_x64_6.1-fastdebug-c2-GROUP, \ + windows_i586_6.2-fastdebug-c2-GROUP, \ + windows_x64_6.2-fastdebug-c2-GROUP, \ linux_i586_2.6-fastdebug-c1-GROUP, \ - windows_i586_6.1-fastdebug-c1-GROUP + windows_i586_6.2-fastdebug-c1-GROUP my.make.rule.test.targets.hotspot= \ ${my.make.rule.test.targets.hotspot.clienttests}, \ diff -r d47c58140b41 -r 427f83353f73 nashorn/.hgtags --- a/nashorn/.hgtags Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/.hgtags Mon Apr 06 10:35:43 2015 -0700 @@ -289,3 +289,5 @@ 6cd23482ca9bd0caa6bfa6bf9064251178083d17 jdk9-b53 26460b897225010a4c7664eaff7a71f1156cacb3 jdk9-b54 b2b332e64b7b2e06e25bccae9c0c0b585a03b4b5 jdk9-b55 +2e640036000dfadcadaf6638b5fd61db9c71a25c jdk9-b56 +3bcfcb13c23402cf435079766eb2f9a3c4f890e8 jdk9-b57 diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Apr 06 10:35:43 2015 -0700 @@ -54,8 +54,10 @@ import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Getter; import jdk.nashorn.internal.objects.annotations.Property; import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.objects.annotations.Setter; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAErrors; import jdk.nashorn.internal.runtime.GlobalConstants; @@ -77,6 +79,7 @@ import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.regexp.RegExpResult; import jdk.nashorn.internal.scripts.JO; +import jdk.nashorn.tools.ShellFunctions; /** * Representation of global scope. @@ -88,6 +91,9 @@ private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); + // placeholder value for lazily initialized global objects + private static final Object LAZY_SENTINEL = new Object(); + /** * Optimistic builtin names that require switchpoint invalidation * upon assignment. Overly conservative, but works for now, to avoid @@ -213,20 +219,76 @@ public volatile Object number; /** ECMA 15.1.4.7 Date constructor */ - @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object date; + @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) + public static Object getDate(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.date == LAZY_SENTINEL) { + global.date = global.getBuiltinDate(); + } + return global.date; + } + + @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) + public static void setDate(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.date = value; + } + + private volatile Object date = LAZY_SENTINEL; /** ECMA 15.1.4.8 RegExp constructor */ - @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object regexp; + @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) + public static Object getRegExp(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.regexp == LAZY_SENTINEL) { + global.regexp = global.getBuiltinRegExp(); + } + return global.regexp; + } + + @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) + public static void setRegExp(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.regexp = value; + } + + private volatile Object regexp = LAZY_SENTINEL; /** ECMA 15.12 - The JSON object */ - @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object json; + @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJSON(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.json == LAZY_SENTINEL) { + global.json = global.getBuiltinJSON(); + } + return global.json; + } + + @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) + public static void setJSON(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.json = value; + } + + private volatile Object json = LAZY_SENTINEL; /** Nashorn extension: global.JSAdapter */ - @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object jsadapter; + @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJSAdapter(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.jsadapter == LAZY_SENTINEL) { + global.jsadapter = global.getBuiltinJSAdapter(); + } + return global.jsadapter; + } + + @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) + public static void setJSAdapter(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.jsadapter = value; + } + + private volatile Object jsadapter = LAZY_SENTINEL; /** ECMA 15.8 - The Math object */ @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE) @@ -237,12 +299,40 @@ public volatile Object error; /** EvalError object */ - @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object evalError; + @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) + public static Object getEvalError(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.evalError == LAZY_SENTINEL) { + global.evalError = global.getBuiltinEvalError(); + } + return global.evalError; + } + + @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) + public static void setEvalError(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.evalError = value; + } + + private volatile Object evalError = LAZY_SENTINEL; /** RangeError object */ - @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object rangeError; + @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) + public static Object getRangeError(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.rangeError == LAZY_SENTINEL) { + global.rangeError = global.getBuiltinRangeError(); + } + return global.rangeError; + } + + @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) + public static void setRangeError(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.rangeError = value; + } + + private volatile Object rangeError = LAZY_SENTINEL; /** ReferenceError object */ @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE) @@ -257,52 +347,220 @@ public volatile Object typeError; /** URIError object */ - @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uriError; + @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) + public static Object getURIError(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uriError == LAZY_SENTINEL) { + global.uriError = global.getBuiltinURIError(); + } + return global.uriError; + } + + @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) + public static void setURIError(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uriError = value; + } + + private volatile Object uriError = LAZY_SENTINEL; /** ArrayBuffer object */ - @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object arrayBuffer; + @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) + public static Object getArrayBuffer(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.arrayBuffer == LAZY_SENTINEL) { + global.arrayBuffer = global.getBuiltinArrayBuffer(); + } + return global.arrayBuffer; + } + + @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) + public static void setArrayBuffer(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.arrayBuffer = value; + } + + private volatile Object arrayBuffer; /** DataView object */ - @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object dataView; + @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) + public static Object getDataView(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.dataView == LAZY_SENTINEL) { + global.dataView = global.getBuiltinDataView(); + } + return global.dataView; + } + + @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) + public static void setDataView(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.dataView = value; + } + + private volatile Object dataView; /** TypedArray (int8) */ - @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object int8Array; + @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getInt8Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.int8Array == LAZY_SENTINEL) { + global.int8Array = global.getBuiltinInt8Array(); + } + return global.int8Array; + } + + @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setInt8Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.int8Array = value; + } + + private volatile Object int8Array; /** TypedArray (uint8) */ - @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint8Array; + @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint8Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint8Array == LAZY_SENTINEL) { + global.uint8Array = global.getBuiltinUint8Array(); + } + return global.uint8Array; + } + + @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint8Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint8Array = value; + } + + private volatile Object uint8Array; /** TypedArray (uint8) - Clamped */ - @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint8ClampedArray; + @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint8ClampedArray(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint8ClampedArray == LAZY_SENTINEL) { + global.uint8ClampedArray = global.getBuiltinUint8ClampedArray(); + } + return global.uint8ClampedArray; + } + + @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint8ClampedArray(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint8ClampedArray = value; + } + + private volatile Object uint8ClampedArray; /** TypedArray (int16) */ - @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object int16Array; + @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getInt16Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.int16Array == LAZY_SENTINEL) { + global.int16Array = global.getBuiltinInt16Array(); + } + return global.int16Array; + } + + @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setInt16Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.int16Array = value; + } + + private volatile Object int16Array; /** TypedArray (uint16) */ - @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint16Array; + @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint16Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint16Array == LAZY_SENTINEL) { + global.uint16Array = global.getBuiltinUint16Array(); + } + return global.uint16Array; + } + + @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint16Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint16Array = value; + } + + private volatile Object uint16Array; /** TypedArray (int32) */ - @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object int32Array; + @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getInt32Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.int32Array == LAZY_SENTINEL) { + global.int32Array = global.getBuiltinInt32Array(); + } + return global.int32Array; + } + + @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setInt32Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.int32Array = value; + } + + private volatile Object int32Array; /** TypedArray (uint32) */ - @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint32Array; + @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint32Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint32Array == LAZY_SENTINEL) { + global.uint32Array = global.getBuiltinUint32Array(); + } + return global.uint32Array; + } + + @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint32Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint32Array = value; + } + + private volatile Object uint32Array; /** TypedArray (float32) */ - @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object float32Array; + @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getFloat32Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.float32Array == LAZY_SENTINEL) { + global.float32Array = global.getBuiltinFloat32Array(); + } + return global.float32Array; + } + + @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setFloat32Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.float32Array = value; + } + + private volatile Object float32Array; /** TypedArray (float64) */ - @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object float64Array; + @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getFloat64Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.float64Array == LAZY_SENTINEL) { + global.float64Array = global.getBuiltinFloat64Array(); + } + return global.float64Array; + } + + @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setFloat64Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.float64Array = value; + } + + private volatile Object float64Array; /** Nashorn extension: Java access - global.Packages */ @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) @@ -333,12 +591,40 @@ public volatile Object org; /** Nashorn extension: Java access - global.javaImporter */ - @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object javaImporter; + @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJavaImporter(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.javaImporter == LAZY_SENTINEL) { + global.javaImporter = global.getBuiltinJavaImporter(); + } + return global.javaImporter; + } + + @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) + public static void setJavaImporter(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.javaImporter = value; + } + + private volatile Object javaImporter; /** Nashorn extension: global.Java Object constructor. */ - @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object javaApi; + @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJavaApi(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.javaApi == LAZY_SENTINEL) { + global.javaApi = global.getBuiltinJavaApi(); + } + return global.javaApi; + } + + @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) + public static void setJavaApi(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.javaApi = value; + } + + private volatile Object javaApi; /** Nashorn extension: current script's file name */ @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) @@ -352,11 +638,19 @@ @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER; + private volatile NativeDate DEFAULT_DATE; + /** Used as Date.prototype's default value */ - public NativeDate DEFAULT_DATE; + NativeDate getDefaultDate() { + return DEFAULT_DATE; + } + + private volatile NativeRegExp DEFAULT_REGEXP; /** Used as RegExp.prototype's default value */ - public NativeRegExp DEFAULT_REGEXP; + NativeRegExp getDefaultRegExp() { + return DEFAULT_REGEXP; + } /* * Built-in constructor objects: Even if user changes dynamic values of @@ -1033,7 +1327,7 @@ /** * Get the builtin Object prototype. - * @return the object prototype. + * @return the object prototype. */ public ScriptObject getObjectPrototype() { return ScriptFunction.getPrototype(builtinObject); @@ -1056,11 +1350,11 @@ } ScriptObject getDatePrototype() { - return ScriptFunction.getPrototype(builtinDate); + return ScriptFunction.getPrototype(getBuiltinDate()); } ScriptObject getRegExpPrototype() { - return ScriptFunction.getPrototype(builtinRegExp); + return ScriptFunction.getPrototype(getBuiltinRegExp()); } ScriptObject getStringPrototype() { @@ -1072,11 +1366,11 @@ } ScriptObject getEvalErrorPrototype() { - return ScriptFunction.getPrototype(builtinEvalError); + return ScriptFunction.getPrototype(getBuiltinEvalError()); } ScriptObject getRangeErrorPrototype() { - return ScriptFunction.getPrototype(builtinRangeError); + return ScriptFunction.getPrototype(getBuiltinRangeError()); } ScriptObject getReferenceErrorPrototype() { @@ -1092,59 +1386,136 @@ } ScriptObject getURIErrorPrototype() { - return ScriptFunction.getPrototype(builtinURIError); + return ScriptFunction.getPrototype(getBuiltinURIError()); } ScriptObject getJavaImporterPrototype() { - return ScriptFunction.getPrototype(builtinJavaImporter); + return ScriptFunction.getPrototype(getBuiltinJavaImporter()); } ScriptObject getJSAdapterPrototype() { - return ScriptFunction.getPrototype(builtinJSAdapter); + return ScriptFunction.getPrototype(getBuiltinJSAdapter()); + } + + private synchronized ScriptFunction getBuiltinArrayBuffer() { + if (this.builtinArrayBuffer == null) { + this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); + } + return this.builtinArrayBuffer; } ScriptObject getArrayBufferPrototype() { - return ScriptFunction.getPrototype(builtinArrayBuffer); + return ScriptFunction.getPrototype(getBuiltinArrayBuffer()); + } + + private synchronized ScriptFunction getBuiltinDataView() { + if (this.builtinDataView == null) { + this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); + } + return this.builtinDataView; } ScriptObject getDataViewPrototype() { - return ScriptFunction.getPrototype(builtinDataView); + return ScriptFunction.getPrototype(getBuiltinDataView()); + } + + private synchronized ScriptFunction getBuiltinInt8Array() { + if (this.builtinInt8Array == null) { + this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); + } + return this.builtinInt8Array; } ScriptObject getInt8ArrayPrototype() { - return ScriptFunction.getPrototype(builtinInt8Array); + return ScriptFunction.getPrototype(getBuiltinInt8Array()); + } + + private synchronized ScriptFunction getBuiltinUint8Array() { + if (this.builtinUint8Array == null) { + this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); + } + return this.builtinUint8Array; } ScriptObject getUint8ArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint8Array); + return ScriptFunction.getPrototype(getBuiltinUint8Array()); + } + + private synchronized ScriptFunction getBuiltinUint8ClampedArray() { + if (this.builtinUint8ClampedArray == null) { + this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); + } + return this.builtinUint8ClampedArray; } ScriptObject getUint8ClampedArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint8ClampedArray); + return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray()); + } + + private synchronized ScriptFunction getBuiltinInt16Array() { + if (this.builtinInt16Array == null) { + this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); + } + return this.builtinInt16Array; } ScriptObject getInt16ArrayPrototype() { - return ScriptFunction.getPrototype(builtinInt16Array); + return ScriptFunction.getPrototype(getBuiltinInt16Array()); + } + + private synchronized ScriptFunction getBuiltinUint16Array() { + if (this.builtinUint16Array == null) { + this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); + } + return this.builtinUint16Array; } ScriptObject getUint16ArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint16Array); + return ScriptFunction.getPrototype(getBuiltinUint16Array()); + } + + private synchronized ScriptFunction getBuiltinInt32Array() { + if (this.builtinInt32Array == null) { + this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); + } + return this.builtinInt32Array; } ScriptObject getInt32ArrayPrototype() { - return ScriptFunction.getPrototype(builtinInt32Array); + return ScriptFunction.getPrototype(getBuiltinInt32Array()); + } + + private synchronized ScriptFunction getBuiltinUint32Array() { + if (this.builtinUint32Array == null) { + this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); + } + return this.builtinUint32Array; } ScriptObject getUint32ArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint32Array); + return ScriptFunction.getPrototype(getBuiltinUint32Array()); + } + + private synchronized ScriptFunction getBuiltinFloat32Array() { + if (this.builtinFloat32Array == null) { + this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); + } + return this.builtinFloat32Array; } ScriptObject getFloat32ArrayPrototype() { - return ScriptFunction.getPrototype(builtinFloat32Array); + return ScriptFunction.getPrototype(getBuiltinFloat32Array()); + } + + private synchronized ScriptFunction getBuiltinFloat64Array() { + if (this.builtinFloat64Array == null) { + this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); + } + return this.builtinFloat64Array; } ScriptObject getFloat64ArrayPrototype() { - return ScriptFunction.getPrototype(builtinFloat64Array); + return ScriptFunction.getPrototype(getBuiltinFloat64Array()); } private ScriptFunction getBuiltinArray() { @@ -1179,8 +1550,14 @@ return instance._boolean == instance.getBuiltinBoolean(); } - private ScriptFunction getBuiltinDate() { - return builtinDate; + private synchronized ScriptFunction getBuiltinDate() { + if (this.builtinDate == null) { + this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); + final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate); + // initialize default date + this.DEFAULT_DATE = new NativeDate(NaN, dateProto); + } + return this.builtinDate; } /** @@ -1190,7 +1567,7 @@ */ public static boolean isBuiltinDate() { final Global instance = Global.instance(); - return instance.date == instance.getBuiltinDate(); + return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate(); } private ScriptFunction getBuiltinError() { @@ -1207,8 +1584,11 @@ return instance.error == instance.getBuiltinError(); } - private ScriptFunction getBuiltinEvalError() { - return builtinEvalError; + private synchronized ScriptFunction getBuiltinEvalError() { + if (this.builtinEvalError == null) { + this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype()); + } + return this.builtinEvalError; } /** @@ -1218,7 +1598,7 @@ */ public static boolean isBuiltinEvalError() { final Global instance = Global.instance(); - return instance.evalError == instance.getBuiltinEvalError(); + return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError(); } private ScriptFunction getBuiltinFunction() { @@ -1269,7 +1649,10 @@ return isBuiltinFunctionProperty("call"); } - private ScriptFunction getBuiltinJSAdapter() { + private synchronized ScriptFunction getBuiltinJSAdapter() { + if (this.builtinJSAdapter == null) { + this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); + } return builtinJSAdapter; } @@ -1280,11 +1663,14 @@ */ public static boolean isBuiltinJSAdapter() { final Global instance = Global.instance(); - return instance.jsadapter == instance.getBuiltinJSAdapter(); + return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter(); } - private ScriptObject getBuiltinJSON() { - return builtinJSON; + private synchronized ScriptObject getBuiltinJSON() { + if (this.builtinJSON == null) { + this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); + } + return this.builtinJSON; } /** @@ -1294,7 +1680,7 @@ */ public static boolean isBuiltinJSON() { final Global instance = Global.instance(); - return instance.json == instance.getBuiltinJSON(); + return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON(); } private ScriptObject getBuiltinJava() { @@ -1325,8 +1711,18 @@ return instance.javax == instance.getBuiltinJavax(); } - private ScriptObject getBuiltinJavaImporter() { - return builtinJavaImporter; + private synchronized ScriptFunction getBuiltinJavaImporter() { + if (this.builtinJavaImporter == null) { + this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); + } + return this.builtinJavaImporter; + } + + private synchronized ScriptObject getBuiltinJavaApi() { + if (this.builtinJavaApi == null) { + this.builtinJavaApi = initConstructor("Java", ScriptObject.class); + } + return this.builtinJavaApi; } /** @@ -1336,11 +1732,7 @@ */ public static boolean isBuiltinJavaImporter() { final Global instance = Global.instance(); - return instance.javaImporter == instance.getBuiltinJavaImporter(); - } - - private ScriptObject getBuiltinMath() { - return builtinMath; + return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter(); } /** @@ -1350,7 +1742,7 @@ */ public static boolean isBuiltinMath() { final Global instance = Global.instance(); - return instance.math == instance.getBuiltinMath(); + return instance.math == instance.builtinMath; } private ScriptFunction getBuiltinNumber() { @@ -1395,7 +1787,10 @@ return instance.packages == instance.getBuiltinPackages(); } - private ScriptFunction getBuiltinRangeError() { + private synchronized ScriptFunction getBuiltinRangeError() { + if (this.builtinRangeError == null) { + this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); + } return builtinRangeError; } @@ -1406,10 +1801,10 @@ */ public static boolean isBuiltinRangeError() { final Global instance = Global.instance(); - return instance.rangeError == instance.getBuiltinRangeError(); + return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError(); } - private ScriptFunction getBuiltinReferenceError() { + private synchronized ScriptFunction getBuiltinReferenceError() { return builtinReferenceError; } @@ -1423,7 +1818,16 @@ return instance.referenceError == instance.getBuiltinReferenceError(); } - private ScriptFunction getBuiltinRegExp() { + private synchronized ScriptFunction getBuiltinRegExp() { + if (this.builtinRegExp == null) { + this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); + final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp); + // initialize default regexp object + this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto); + // RegExp.prototype should behave like a RegExp object. So copy the + // properties. + regExpProto.addBoundProperties(DEFAULT_REGEXP); + } return builtinRegExp; } @@ -1434,7 +1838,7 @@ */ public static boolean isBuiltinRegExp() { final Global instance = Global.instance(); - return instance.regexp == instance.getBuiltinRegExp(); + return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp(); } private ScriptFunction getBuiltinString() { @@ -1479,8 +1883,11 @@ return instance.typeError == instance.getBuiltinTypeError(); } - private ScriptFunction getBuiltinURIError() { - return builtinURIError; + private synchronized ScriptFunction getBuiltinURIError() { + if (this.builtinURIError == null) { + this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); + } + return this.builtinURIError; } /** @@ -1490,7 +1897,7 @@ */ public static boolean isBuiltinURIError() { final Global instance = Global.instance(); - return instance.uriError == instance.getBuiltinURIError(); + return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError(); } @Override @@ -1816,6 +2223,17 @@ return invocation; } + /** + * Adds jjs shell interactive mode builtin functions to global scope. + */ + public void addShellBuiltins() { + Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT); + addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); + + value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT); + addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); + } + private synchronized SwitchPoint getLexicalScopeSwitchPoint() { SwitchPoint switchPoint = lexicalScopeSwitchPoint; if (switchPoint == null || switchPoint.hasBeenInvalidated()) { @@ -1891,13 +2309,9 @@ // built-in constructors this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); - this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); - this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); - this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); + this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); + this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); - this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); - this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); - this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); // initialize String.prototype.length to 0 // add String.prototype.length @@ -1908,26 +2322,28 @@ final ScriptObject arrayPrototype = getArrayPrototype(); arrayPrototype.setIsArray(); - this.DEFAULT_DATE = new NativeDate(Double.NaN, this); - - // initialize default regexp object - this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this); - - // RegExp.prototype should behave like a RegExp object. So copy the - // properties. - final ScriptObject regExpProto = getRegExpPrototype(); - regExpProto.addBoundProperties(DEFAULT_REGEXP); - // Error stuff initErrorObjects(); // java access if (! env._no_java) { + this.javaApi = LAZY_SENTINEL; + this.javaImporter = LAZY_SENTINEL; initJavaAccess(); } if (! env._no_typed_arrays) { - initTypedArray(); + this.arrayBuffer = LAZY_SENTINEL; + this.dataView = LAZY_SENTINEL; + this.int8Array = LAZY_SENTINEL; + this.uint8Array = LAZY_SENTINEL; + this.uint8ClampedArray = LAZY_SENTINEL; + this.int16Array = LAZY_SENTINEL; + this.uint16Array = LAZY_SENTINEL; + this.int32Array = LAZY_SENTINEL; + this.uint32Array = LAZY_SENTINEL; + this.float32Array = LAZY_SENTINEL; + this.float64Array = LAZY_SENTINEL; } if (env._scripting) { @@ -2001,12 +2417,9 @@ tagBuiltinProperties("Error", builtinError); - this.builtinEvalError = initErrorSubtype("EvalError", errorProto); - this.builtinRangeError = initErrorSubtype("RangeError", errorProto); this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); this.builtinTypeError = initErrorSubtype("TypeError", errorProto); - this.builtinURIError = initErrorSubtype("URIError", errorProto); } private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { @@ -2028,8 +2441,6 @@ this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); this.builtinJavax = new NativeJavaPackage("javax", objectProto); this.builtinOrg = new NativeJavaPackage("org", objectProto); - this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); - this.builtinJavaApi = initConstructor("Java", ScriptObject.class); } private void initScripting(final ScriptEnvironment scriptEnv) { @@ -2081,60 +2492,25 @@ } } - private void initTypedArray() { - this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); - this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); - this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); - this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); - this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); - this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); - this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); - this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); - this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); - this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); - this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); - - } - private void copyBuiltins() { this.array = this.builtinArray; this._boolean = this.builtinBoolean; - this.date = this.builtinDate; this.error = this.builtinError; - this.evalError = this.builtinEvalError; this.function = this.builtinFunction; - this.jsadapter = this.builtinJSAdapter; - this.json = this.builtinJSON; this.com = this.builtinCom; this.edu = this.builtinEdu; this.java = this.builtinJava; this.javafx = this.builtinJavafx; this.javax = this.builtinJavax; this.org = this.builtinOrg; - this.javaImporter = this.builtinJavaImporter; - this.javaApi = this.builtinJavaApi; this.math = this.builtinMath; this.number = this.builtinNumber; this.object = this.builtinObject; this.packages = this.builtinPackages; - this.rangeError = this.builtinRangeError; this.referenceError = this.builtinReferenceError; - this.regexp = this.builtinRegExp; this.string = this.builtinString; this.syntaxError = this.builtinSyntaxError; this.typeError = this.builtinTypeError; - this.uriError = this.builtinURIError; - this.arrayBuffer = this.builtinArrayBuffer; - this.dataView = this.builtinDataView; - this.int8Array = this.builtinInt8Array; - this.uint8Array = this.builtinUint8Array; - this.uint8ClampedArray = this.builtinUint8ClampedArray; - this.int16Array = this.builtinInt16Array; - this.uint16Array = this.builtinUint16Array; - this.int32Array = this.builtinInt32Array; - this.uint32Array = this.builtinUint32Array; - this.float32Array = this.builtinFloat32Array; - this.float64Array = this.builtinFloat64Array; } private void initDebug() { diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java Mon Apr 06 10:35:43 2015 -0700 @@ -121,6 +121,10 @@ this.timezone = env._timezone; } + NativeDate(final double time, final ScriptObject proto) { + this(time, proto, $nasgenmap$); + } + NativeDate(final double time, final Global global) { this(time, global.getDatePrototype(), $nasgenmap$); } @@ -1276,7 +1280,7 @@ if (self instanceof NativeDate) { return (NativeDate)self; } else if (self != null && self == Global.instance().getDatePrototype()) { - return Global.instance().DEFAULT_DATE; + return Global.instance().getDefaultDate(); } else { throw typeError("not.a.date", ScriptRuntime.safeToString(self)); } diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Mon Apr 06 10:35:43 2015 -0700 @@ -78,8 +78,8 @@ this.globalObject = global; } - NativeRegExp(final String input, final String flagString, final Global global) { - this(global); + NativeRegExp(final String input, final String flagString, final Global global, final ScriptObject proto) { + super(proto, $nasgenmap$); try { this.regexp = RegExpFactory.create(input, flagString); } catch (final ParserException e) { @@ -87,8 +87,12 @@ e.throwAsEcmaException(); throw new AssertionError(); //guard against null warnings below } + this.globalObject = global; + this.setLastIndex(0); + } - this.setLastIndex(0); + NativeRegExp(final String input, final String flagString, final Global global) { + this(input, flagString, global, global.getRegExpPrototype()); } NativeRegExp(final String input, final String flagString) { @@ -928,7 +932,7 @@ if (self instanceof NativeRegExp) { return (NativeRegExp)self; } else if (self != null && self == Global.instance().getRegExpPrototype()) { - return Global.instance().DEFAULT_REGEXP; + return Global.instance().getDefaultRegExp(); } else { throw typeError("not.a.regexp", ScriptRuntime.safeToString(self)); } diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Mon Apr 06 10:35:43 2015 -0700 @@ -933,11 +933,15 @@ if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') { //decode hex string value = parseRadix(str.toCharArray(), start + 2, end, 16); + } else if (f == 'I' && end - start == 8 && str.regionMatches(start, "Infinity", 0, 8)) { + return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; } else { - // Fast (no NumberFormatException) path to NaN for non-numeric strings. We allow those starting with "I" or - // "N" to allow for parsing "NaN" and "Infinity" correctly. - if ((f < '0' || f > '9') && f != '.' && f != 'I' && f != 'N') { - return Double.NaN; + // Fast (no NumberFormatException) path to NaN for non-numeric strings. + for (int i = start; i < end; i++) { + f = str.charAt(i); + if ((f < '0' || f > '9') && f != '.' && f != 'e' && f != 'E' && f != '+' && f != '-') { + return Double.NaN; + } } try { value = Double.parseDouble(str.substring(start, end)); diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/fx/base.js --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/fx/base.js Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/fx/base.js Mon Apr 06 10:35:43 2015 -0700 @@ -45,11 +45,19 @@ var SUFFIX_LENGTH = ".class".length; + // TODO - temporary patch until fx is moved to module system. + // + var jfxrtJar; try { - var jfxrtJar = new ZipFile(System.getProperty("java.home") + "/lib/ext/jfxrt.jar"); - } catch (ex) { - throw new Error("JavaFX runtime not found"); + jfxrtJar = new ZipFile(System.getProperty("java.home") + "/lib/jfxrt.jar"); + } catch (ex1) { + try { + jfxrtJar = new ZipFile(System.getProperty("java.home") + "/lib/ext/jfxrt.jar"); + } catch (ex2) { + throw new Error("JavaFX runtime not found"); + } } + // var entries = jfxrtJar.entries(); diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Mon Apr 06 10:35:43 2015 -0700 @@ -417,18 +417,7 @@ Context.setGlobal(global); } - // initialize with "shell.js" script - try { - final Source source = sourceFor("", Shell.class.getResource("resources/shell.js")); - context.eval(global, source.getString(), global, "", false); - } catch (final Exception e) { - err.println(e); - if (env._dump_on_error) { - e.printStackTrace(err); - } - - return INTERNAL_ERROR; - } + global.addShellBuiltins(); while (true) { err.print(prompt); diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java Mon Apr 06 10:35:43 2015 -0700 @@ -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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.tools; + +import static jdk.nashorn.internal.lookup.Lookup.MH; +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.objects.Global; + +/** + * Global functions supported only in shell interactive mode. + */ +public final class ShellFunctions { + + /** Handle to implementation of {@link ShellFunctions#input} - Nashorn extension */ + public static final MethodHandle INPUT = findOwnMH("input", Object.class, Object.class, Object.class, Object.class); + + /** Handle to implementation of {@link ShellFunctions#evalinput} - Nashorn extension */ + public static final MethodHandle EVALINPUT = findOwnMH("evalinput", Object.class, Object.class, Object.class, Object.class); + + private ShellFunctions() { + } + + /** + * Nashorn extension: global.input (shell-interactive-mode-only) + * Read one or more lines of input from the standard input till the + * given end marker is seen in standard input. + * + * @param self self reference + * @param endMarker String used as end marker for input + * @param prompt String used as input prompt + * + * @return line that was read + * + * @throws IOException if an exception occurs + */ + public static Object input(final Object self, final Object endMarker, final Object prompt) throws IOException { + final String endMarkerStr = (endMarker != UNDEFINED)? JSType.toString(endMarker) : ""; + final String promptStr = (prompt != UNDEFINED)? JSType.toString(prompt) : ">> "; + final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + final StringBuilder buf = new StringBuilder(); + while (true) { + System.out.print(promptStr); + final String line = reader.readLine(); + if (line == null || line.equals(endMarkerStr)) { + break; + } + buf.append(line); + buf.append('\n'); + } + return buf.toString(); + } + + /** + * Nashorn extension: Reads zero or more lines from standard input and + * evaluates the concatenated string as code + * + * @param self self reference + * @param endMarker String used as end marker for input + * @param prompt String used as input prompt + * + * @return output from evaluating the script + * + * @throws IOException if an exception occurs + */ + public static Object evalinput(final Object self, final Object endMarker, final Object prompt) throws IOException { + return Global.eval(self, input(self, endMarker, prompt)); + } + + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { + return MH.findStatic(MethodHandles.lookup(), ShellFunctions.class, name, MH.type(rtype, types)); + } +} diff -r d47c58140b41 -r 427f83353f73 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/resources/shell.js --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/resources/shell.js Tue Mar 31 16:22:59 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Initialization script for shell when running in interactive mode. - */ - -/** - * Reads zero or more lines from standard input and returns concatenated string - * - * @param endMarker marker string that signals end of input - * @param prompt prompt printed for each line - */ -Object.defineProperty(this, "input", { - value: function input(endMarker, prompt) { - if (!endMarker) { - endMarker = ""; - } - - if (!prompt) { - prompt = " >> "; - } - - var imports = new JavaImporter(java.io, java.lang); - var str = ""; - with (imports) { - var reader = new BufferedReader(new InputStreamReader(System['in'])); - var line; - while (true) { - System.out.print(prompt); - line = reader.readLine(); - if (line == null || line == endMarker) { - break; - } - str += line + "\n"; - } - } - - return str; - }, - enumerable: false, - writable: true, - configurable: true -}); - - -/** - * Reads zero or more lines from standard input and evaluates the concatenated - * string as code - * - * @param endMarker marker string that signals end of input - * @param prompt prompt printed for each line - */ -Object.defineProperty(this, "evalinput", { - value: function evalinput(endMarker, prompt) { - var code = input(endMarker, prompt); - // make sure everything is evaluated in global scope! - return this.eval(code); - }, - enumerable: false, - writable: true, - configurable: true -}); diff -r d47c58140b41 -r 427f83353f73 nashorn/test/script/basic/JDK-8075927.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8075927.js Mon Apr 06 10:35:43 2015 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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-8075927: toNumber(String) accepts illegal characters + * + * @test + * @run + */ + +Assert.assertTrue(isNaN(Number("-123d"))); +Assert.assertTrue(isNaN(Number("-123f"))); +Assert.assertTrue(Number(" 123 ") === 123); +Assert.assertTrue(Number(" -123 ") === -123); +Assert.assertEquals(Number(" Infinity "), Infinity); +Assert.assertEquals(Number(" +Infinity "), Infinity); +Assert.assertEquals(Number(" -Infinity "), -Infinity); + diff -r d47c58140b41 -r 427f83353f73 nashorn/test/script/nosecurity/parserapi.js --- a/nashorn/test/script/nosecurity/parserapi.js Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/test/script/nosecurity/parserapi.js Mon Apr 06 10:35:43 2015 -0700 @@ -97,7 +97,7 @@ var parser = new Parser(); var tree = parser.parse(subdir + "/" + file.name, script, function(diagnostic) { - print(JSON.stringify(parser.convert(diagnostic), null, 2)); + print(JSON.stringify(parser.convert(diagnostic), null, 2).replace(/\\r/g, '')); print(","); }); diff -r d47c58140b41 -r 427f83353f73 nashorn/test/script/nosecurity/parserapi.js.EXPECTED --- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Mon Apr 06 10:35:43 2015 -0700 @@ -1,4 +1,4 @@ -[ +[ { "endPosition": "1113", "kind": "COMPILATION_UNIT", @@ -132,8 +132,8 @@ "sourceName": "parsertests/array_literal.js", "strict": "false", "startPosition": "1113" -} -, +} +, { "endPosition": "1126", "kind": "COMPILATION_UNIT", @@ -406,8 +406,8 @@ "sourceName": "parsertests/assignmentExpr.js", "strict": "false", "startPosition": "1126" -} -, +} +, { "endPosition": "1116", "kind": "COMPILATION_UNIT", @@ -912,8 +912,8 @@ "sourceName": "parsertests/binaryExpr.js", "strict": "false", "startPosition": "1116" -} -, +} +, { "endPosition": "1117", "kind": "COMPILATION_UNIT", @@ -959,8 +959,8 @@ "sourceName": "parsertests/block.js", "strict": "false", "startPosition": "1117" -} -, +} +, { "endPosition": "1117", "kind": "COMPILATION_UNIT", @@ -1060,8 +1060,8 @@ "sourceName": "parsertests/breakStat.js", "strict": "false", "startPosition": "1117" -} -, +} +, { "endPosition": "1117", "kind": "COMPILATION_UNIT", @@ -1098,8 +1098,8 @@ "sourceName": "parsertests/condExpr.js", "strict": "false", "startPosition": "1117" -} -, +} +, { "endPosition": "1120", "kind": "COMPILATION_UNIT", @@ -1199,8 +1199,8 @@ "sourceName": "parsertests/continueStat.js", "strict": "false", "startPosition": "1120" -} -, +} +, { "endPosition": "1118", "kind": "COMPILATION_UNIT", @@ -1214,8 +1214,8 @@ "sourceName": "parsertests/debuggerStat.js", "strict": "false", "startPosition": "1118" -} -, +} +, { "endPosition": "1137", "kind": "COMPILATION_UNIT", @@ -1500,8 +1500,8 @@ "sourceName": "parsertests/functions.js", "strict": "false", "startPosition": "1137" -} -, +} +, { "endPosition": "1114", "kind": "COMPILATION_UNIT", @@ -1604,8 +1604,8 @@ "sourceName": "parsertests/ifStat.js", "strict": "false", "startPosition": "1114" -} -, +} +, { "endPosition": "1113", "kind": "COMPILATION_UNIT", @@ -1668,8 +1668,8 @@ "sourceName": "parsertests/labelledStat.js", "strict": "false", "startPosition": "1113" -} -, +} +, { "endPosition": "1125", "kind": "COMPILATION_UNIT", @@ -2066,8 +2066,8 @@ "sourceName": "parsertests/lhsExpr.js", "strict": "false", "startPosition": "1125" -} -, +} +, { "endPosition": "1110", "kind": "COMPILATION_UNIT", @@ -2350,8 +2350,8 @@ "sourceName": "parsertests/loopStat.js", "strict": "false", "startPosition": "1110" -} -, +} +, { "endPosition": "1125", "kind": "COMPILATION_UNIT", @@ -2705,8 +2705,8 @@ "sourceName": "parsertests/objectLitExpr.js", "strict": "false", "startPosition": "1125" -} -, +} +, { "endPosition": "1118", "kind": "COMPILATION_UNIT", @@ -2781,8 +2781,8 @@ "sourceName": "parsertests/parenExpr.js", "strict": "false", "startPosition": "1118" -} -, +} +, { "endPosition": "1119", "kind": "COMPILATION_UNIT", @@ -2995,8 +2995,8 @@ "sourceName": "parsertests/primaryExpr.js", "strict": "false", "startPosition": "1119" -} -, +} +, { "endPosition": "1114", "kind": "COMPILATION_UNIT", @@ -3044,8 +3044,8 @@ "sourceName": "parsertests/regexp_literal.js", "strict": "false", "startPosition": "1114" -} -, +} +, { "endPosition": "1118", "kind": "COMPILATION_UNIT", @@ -3144,8 +3144,8 @@ "sourceName": "parsertests/returnStat.js", "strict": "false", "startPosition": "1118" -} -, +} +, { "endPosition": "1111", "kind": "COMPILATION_UNIT", @@ -3309,8 +3309,8 @@ "sourceName": "parsertests/switchStat.js", "strict": "false", "startPosition": "1111" -} -, +} +, { "endPosition": "1110", "kind": "COMPILATION_UNIT", @@ -3421,8 +3421,8 @@ "sourceName": "parsertests/throwStat.js", "strict": "false", "startPosition": "1110" -} -, +} +, { "endPosition": "1121", "kind": "COMPILATION_UNIT", @@ -3783,8 +3783,8 @@ "sourceName": "parsertests/tryCatchStat.js", "strict": "false", "startPosition": "1121" -} -, +} +, { "endPosition": "1115", "kind": "COMPILATION_UNIT", @@ -3969,8 +3969,8 @@ "sourceName": "parsertests/unaryExpr.js", "strict": "false", "startPosition": "1115" -} -, +} +, { "endPosition": "1122", "kind": "COMPILATION_UNIT", @@ -4016,8 +4016,8 @@ "sourceName": "parsertests/useStrict.js", "strict": "true", "startPosition": "1122" -} -, +} +, { "endPosition": "1143", "kind": "COMPILATION_UNIT", @@ -4092,8 +4092,8 @@ "sourceName": "parsertests/varDecl.js", "strict": "false", "startPosition": "1143" -} -, +} +, { "endPosition": "1111", "kind": "COMPILATION_UNIT", @@ -4142,8 +4142,8 @@ "sourceName": "parsertests/withStat.js", "strict": "false", "startPosition": "1111" -} -, +} +, { "fileName": "parsernegativetests/caseoutofswitch.js", "code": "case (1090, 4)", @@ -4152,8 +4152,8 @@ "position": "1090", "message": "parsernegativetests/caseoutofswitch.js:29:0 Expected an operand but found case\ncase 23:\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/caseoutofswitch.js", "code": "default (1112, 7)", @@ -4162,8 +4162,8 @@ "position": "1112", "message": "parsernegativetests/caseoutofswitch.js:31:0 Expected an operand but found default\ndefault:\n^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4240,8 +4240,8 @@ "sourceName": "parsernegativetests/caseoutofswitch.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegalbreak.js", "code": "break (1090, 5)", @@ -4250,8 +4250,8 @@ "position": "1090", "message": "parsernegativetests/illegalbreak.js:29:0 Illegal break statement\nbreak;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/illegalbreak.js", "code": "ident (1103, 3)", @@ -4260,8 +4260,8 @@ "position": "1103", "message": "parsernegativetests/illegalbreak.js:30:6 Undefined Label \"foo\"\nbreak foo;\n ^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4290,8 +4290,8 @@ "sourceName": "parsernegativetests/illegalbreak.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegalcontinue.js", "code": "continue (1090, 8)", @@ -4300,8 +4300,8 @@ "position": "1090", "message": "parsernegativetests/illegalcontinue.js:29:0 Illegal continue statement\ncontinue;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/illegalcontinue.js", "code": "ident (1109, 3)", @@ -4310,8 +4310,8 @@ "position": "1109", "message": "parsernegativetests/illegalcontinue.js:30:9 Undefined Label \"foo\"\ncontinue foo;\n ^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4340,8 +4340,8 @@ "sourceName": "parsernegativetests/illegalcontinue.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegallvalue.js", "code": "decimal (1090, 2)", @@ -4350,8 +4350,8 @@ "position": "1090", "message": "parsernegativetests/illegallvalue.js:29:0 Invalid left hand side for assignment\n44 = 54;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/illegallvalue.js", "code": "decimal (1099, 3)", @@ -4360,8 +4360,8 @@ "position": "1099", "message": "parsernegativetests/illegallvalue.js:30:0 Invalid left hand side for assignment\n233 += 33;\n^", "lineNumber": "30" -} -, +} +, { "fileName": "parsernegativetests/illegallvalue.js", "code": "decimal (1110, 4)", @@ -4370,8 +4370,8 @@ "position": "1110", "message": "parsernegativetests/illegallvalue.js:31:0 Invalid left hand side for assignment\n3423 -= 234;\n^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4410,8 +4410,8 @@ "sourceName": "parsernegativetests/illegallvalue.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/illegaloperator.js", "code": "* (1093, 1)", @@ -4420,8 +4420,8 @@ "position": "1093", "message": "parsernegativetests/illegaloperator.js:29:3 Expected an operand but found *\nx ** y\n ^", "lineNumber": "29" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4440,8 +4440,8 @@ "sourceName": "parsernegativetests/illegaloperator.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/keywordident.js", "code": "var (1094, 3)", @@ -4450,8 +4450,8 @@ "position": "1094", "message": "parsernegativetests/keywordident.js:29:4 Expected ident but found var\nvar var = 23;\n ^", "lineNumber": "29" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4482,8 +4482,8 @@ "sourceName": "parsernegativetests/keywordident.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/parenmissing.js", "code": "; (1096, 1)", @@ -4492,8 +4492,8 @@ "position": "1096", "message": "parsernegativetests/parenmissing.js:29:6 Expected ) but found ;\n(1 + 2;\n ^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/parenmissing.js", "code": ") (1103, 1)", @@ -4502,8 +4502,8 @@ "position": "1103", "message": "parsernegativetests/parenmissing.js:30:5 Expected ; but found )\nx * y);\n ^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4554,8 +4554,8 @@ "sourceName": "parsernegativetests/parenmissing.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1111, 3)", @@ -4564,8 +4564,8 @@ "position": "1111", "message": "parsernegativetests/repeatedproperty.js:29:21 Property \"foo\" already defined\nvar obj = { foo: 34, get foo() { return 'hello' } };\n ^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1165, 3)", @@ -4574,8 +4574,8 @@ "position": "1165", "message": "parsernegativetests/repeatedproperty.js:30:22 Property \"foo\" already defined\nvar obj1 = { foo: 34, set foo(x) { } };\n ^", "lineNumber": "30" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1205, 3)", @@ -4584,8 +4584,8 @@ "position": "1205", "message": "parsernegativetests/repeatedproperty.js:31:22 Property \"foo\" already defined\nvar obj2 = { foo: 34, set foo(x) { } };\n ^", "lineNumber": "31" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1251, 3)", @@ -4594,8 +4594,8 @@ "position": "1251", "message": "parsernegativetests/repeatedproperty.js:32:28 Property \"bar\" already defined\nvar obj3 = { get bar() { }, get bar() {} };\n ^", "lineNumber": "32" -} -, +} +, { "fileName": "parsernegativetests/repeatedproperty.js", "code": "ident (1296, 3)", @@ -4604,8 +4604,8 @@ "position": "1296", "message": "parsernegativetests/repeatedproperty.js:33:29 Property \"bar\" already defined\nvar obj4 = { set bar(x) { }, set bar(x) {} };\n ^", "lineNumber": "33" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4664,8 +4664,8 @@ "sourceName": "parsernegativetests/repeatedproperty.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/strict_repeatedproperty.js", "code": "ident (1126, 3)", @@ -4674,8 +4674,8 @@ "position": "1126", "message": "parsernegativetests/strict_repeatedproperty.js:31:21 Property \"foo\" already defined\nvar obj = { foo: 34, foo: 'hello' };\n ^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4705,8 +4705,8 @@ "sourceName": "parsernegativetests/strict_repeatedproperty.js", "strict": "true", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/strict_repeatparam.js", "code": "ident (1119, 1)", @@ -4715,8 +4715,8 @@ "position": "1119", "message": "parsernegativetests/strict_repeatparam.js:31:14 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4746,8 +4746,8 @@ "sourceName": "parsernegativetests/strict_repeatparam.js", "strict": "true", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/strict_with.js", "code": "with (1105, 4)", @@ -4756,8 +4756,8 @@ "position": "1105", "message": "parsernegativetests/strict_with.js:31:0 \"with\" statement cannot be used in strict mode\nwith({}) {}\n^", "lineNumber": "31" -} -, +} +, { "fileName": "parsernegativetests/strict_with.js", "code": ") (1112, 1)", @@ -4766,8 +4766,8 @@ "position": "1112", "message": "parsernegativetests/strict_with.js:31:7 Expected ; but found )\nwith({}) {}\n ^", "lineNumber": "31" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4807,8 +4807,8 @@ "sourceName": "parsernegativetests/strict_with.js", "strict": "true", "startPosition": "1090" -} -, +} +, { "fileName": "parsernegativetests/toplevelreturn.js", "code": "return (1090, 6)", @@ -4817,8 +4817,8 @@ "position": "1090", "message": "parsernegativetests/toplevelreturn.js:29:0 Invalid return statement\nreturn;\n^", "lineNumber": "29" -} -, +} +, { "fileName": "parsernegativetests/toplevelreturn.js", "code": "return (1098, 6)", @@ -4827,8 +4827,8 @@ "position": "1098", "message": "parsernegativetests/toplevelreturn.js:30:0 Invalid return statement\nreturn 23;\n^", "lineNumber": "30" -} -, +} +, { "endPosition": "1090", "kind": "COMPILATION_UNIT", @@ -4857,8 +4857,8 @@ "sourceName": "parsernegativetests/toplevelreturn.js", "strict": "false", "startPosition": "1090" -} -, +} +, { "endPosition": "1136", "kind": "COMPILATION_UNIT", @@ -6189,11 +6189,11 @@ "startPosition": "1972" }, { - "endPosition": "3598", + "endPosition": "3618", "kind": "FUNCTION", "name": "processFiles", "body": { - "endPosition": "3555", + "endPosition": "3575", "kind": "BLOCK", "statements": [ { @@ -6335,7 +6335,7 @@ "name": "files", "startPosition": "3053" }, - "endPosition": "3555", + "endPosition": "3575", "kind": "FOR_IN_LOOP", "forEach": "true", "variable": { @@ -6345,7 +6345,7 @@ "startPosition": "3045" }, "statement": { - "endPosition": "3555", + "endPosition": "3575", "kind": "BLOCK", "statements": [ { @@ -6380,11 +6380,11 @@ ], "startPosition": "3073" }, - "endPosition": "3550", + "endPosition": "3570", "kind": "IF", "startPosition": "3069", "thenStatement": { - "endPosition": "3550", + "endPosition": "3570", "kind": "BLOCK", "statements": [ { @@ -6436,12 +6436,12 @@ } }, { - "endPosition": "3415", + "endPosition": "3435", "kind": "VARIABLE", "name": "tree", "startPosition": "3196", "initializer": { - "endPosition": "3415", + "endPosition": "3435", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "parse", @@ -6500,12 +6500,12 @@ "endPosition": "3286", "kind": "FUNCTION_EXPRESSION", "body": { - "endPosition": "3397", + "endPosition": "3417", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "3365", + "endPosition": "3385", "kind": "FUNCTION_INVOCATION", "functionSelect": { "endPosition": "3312", @@ -6515,90 +6515,116 @@ }, "arguments": [ { - "endPosition": "3364", + "endPosition": "3384", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "identifier": "stringify", + "identifier": "replace", "expression": { - "endPosition": "3317", - "kind": "IDENTIFIER", - "name": "JSON", + "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" }, - "endPosition": "3327", + "endPosition": "3372", "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": "3379", + "kind": "REGEXP_LITERAL", + "options": "g", + "pattern": "\\\\r", + "startPosition": "3373" }, { - "endPosition": "3360", - "kind": "NULL_LITERAL", - "startPosition": "3356" - }, - { - "endPosition": "3363", - "kind": "NUMBER_LITERAL", - "value": "2", - "startPosition": "3362" + "endPosition": "3382", + "kind": "STRING_LITERAL", + "value": "", + "startPosition": "3382" } ], - "startPosition": "3313" + "startPosition": "3372" } ], "startPosition": "3307" }, - "endPosition": "3365", + "endPosition": "3385", "kind": "EXPRESSION_STATEMENT", "startPosition": "3307" }, { "expression": { - "endPosition": "3396", + "endPosition": "3416", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3391", + "endPosition": "3411", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3386" + "startPosition": "3406" }, "arguments": [ { - "endPosition": "3394", + "endPosition": "3414", "kind": "STRING_LITERAL", "value": ",", - "startPosition": "3393" + "startPosition": "3413" } ], - "startPosition": "3386" + "startPosition": "3406" }, - "endPosition": "3396", + "endPosition": "3416", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3386" + "startPosition": "3406" } ], "startPosition": "3286" @@ -6621,107 +6647,107 @@ { "condition": { "leftOperand": { - "endPosition": "3437", + "endPosition": "3457", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "3433" + "startPosition": "3453" }, - "endPosition": "3445", + "endPosition": "3465", "kind": "NOT_EQUAL_TO", "rightOperand": { - "endPosition": "3445", + "endPosition": "3465", "kind": "NULL_LITERAL", - "startPosition": "3441" + "startPosition": "3461" }, - "startPosition": "3433" + "startPosition": "3453" }, - "endPosition": "3541", + "endPosition": "3561", "kind": "IF", - "startPosition": "3429", + "startPosition": "3449", "thenStatement": { - "endPosition": "3541", + "endPosition": "3561", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "3500", + "endPosition": "3520", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3469", + "endPosition": "3489", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3464" + "startPosition": "3484" }, "arguments": [ { - "endPosition": "3499", + "endPosition": "3519", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "stringify", "expression": { - "endPosition": "3474", + "endPosition": "3494", "kind": "IDENTIFIER", "name": "JSON", - "startPosition": "3470" + "startPosition": "3490" }, - "endPosition": "3484", + "endPosition": "3504", "kind": "MEMBER_SELECT", - "startPosition": "3470" + "startPosition": "3490" }, "arguments": [ { - "endPosition": "3489", + "endPosition": "3509", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "3485" + "startPosition": "3505" }, { - "endPosition": "3495", + "endPosition": "3515", "kind": "NULL_LITERAL", - "startPosition": "3491" + "startPosition": "3511" }, { - "endPosition": "3498", + "endPosition": "3518", "kind": "NUMBER_LITERAL", "value": "2", - "startPosition": "3497" + "startPosition": "3517" } ], - "startPosition": "3470" + "startPosition": "3490" } ], - "startPosition": "3464" + "startPosition": "3484" }, - "endPosition": "3500", + "endPosition": "3520", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3464" + "startPosition": "3484" }, { "expression": { - "endPosition": "3527", + "endPosition": "3547", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3522", + "endPosition": "3542", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3517" + "startPosition": "3537" }, "arguments": [ { - "endPosition": "3525", + "endPosition": "3545", "kind": "STRING_LITERAL", "value": ",", - "startPosition": "3524" + "startPosition": "3544" } ], - "startPosition": "3517" + "startPosition": "3537" }, - "endPosition": "3527", + "endPosition": "3547", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3517" + "startPosition": "3537" } ], - "startPosition": "3447" + "startPosition": "3467" } } ], @@ -6748,268 +6774,268 @@ ] }, { - "endPosition": "3901", + "endPosition": "3921", "kind": "FUNCTION", "name": "main", "body": { - "endPosition": "3899", + "endPosition": "3919", "kind": "BLOCK", "statements": [ { "expression": { - "endPosition": "3631", + "endPosition": "3651", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3626", + "endPosition": "3646", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3621" + "startPosition": "3641" }, "arguments": [ { - "endPosition": "3629", + "endPosition": "3649", "kind": "STRING_LITERAL", "value": "[", - "startPosition": "3628" + "startPosition": "3648" } ], - "startPosition": "3621" + "startPosition": "3641" }, - "endPosition": "3631", + "endPosition": "3651", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3621" + "startPosition": "3641" }, { "expression": { - "endPosition": "3665", + "endPosition": "3685", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3650", + "endPosition": "3670", "kind": "IDENTIFIER", "name": "processFiles", - "startPosition": "3638" + "startPosition": "3658" }, "arguments": [ { - "endPosition": "3663", + "endPosition": "3683", "kind": "STRING_LITERAL", "value": "parsertests", - "startPosition": "3652" + "startPosition": "3672" } ], - "startPosition": "3638" + "startPosition": "3658" }, - "endPosition": "3665", + "endPosition": "3685", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3638" + "startPosition": "3658" }, { "expression": { - "endPosition": "3706", + "endPosition": "3726", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3683", + "endPosition": "3703", "kind": "IDENTIFIER", "name": "processFiles", - "startPosition": "3671" + "startPosition": "3691" }, "arguments": [ { - "endPosition": "3704", + "endPosition": "3724", "kind": "STRING_LITERAL", "value": "parsernegativetests", - "startPosition": "3685" + "startPosition": "3705" } ], - "startPosition": "3671" + "startPosition": "3691" }, - "endPosition": "3706", + "endPosition": "3726", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3671" + "startPosition": "3691" }, { - "endPosition": "3775", + "endPosition": "3795", "kind": "VARIABLE", "name": "script", - "startPosition": "3747", + "startPosition": "3767", "initializer": { - "endPosition": "3775", + "endPosition": "3795", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3765", + "endPosition": "3785", "kind": "IDENTIFIER", "name": "readFully", - "startPosition": "3756" + "startPosition": "3776" }, "arguments": [ { - "endPosition": "3774", + "endPosition": "3794", "kind": "IDENTIFIER", "name": "__FILE__", - "startPosition": "3766" + "startPosition": "3786" } ], - "startPosition": "3756" + "startPosition": "3776" } }, { - "endPosition": "3840", + "endPosition": "3860", "kind": "VARIABLE", "name": "tree", - "startPosition": "3785", + "startPosition": "3805", "initializer": { - "endPosition": "3840", + "endPosition": "3860", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "parse", "expression": { "constructorExpression": { - "endPosition": "3804", + "endPosition": "3824", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3802", + "endPosition": "3822", "kind": "IDENTIFIER", "name": "Parser", - "startPosition": "3796" + "startPosition": "3816" }, "arguments": [], - "startPosition": "3796" + "startPosition": "3816" }, - "endPosition": "3804", + "endPosition": "3824", "kind": "NEW", - "startPosition": "3792" + "startPosition": "3812" }, - "endPosition": "3810", + "endPosition": "3830", "kind": "MEMBER_SELECT", - "startPosition": "3792" + "startPosition": "3812" }, "arguments": [ { - "endPosition": "3824", + "endPosition": "3844", "kind": "STRING_LITERAL", "value": "parserapi.js", - "startPosition": "3812" + "startPosition": "3832" }, { - "endPosition": "3833", + "endPosition": "3853", "kind": "IDENTIFIER", "name": "script", - "startPosition": "3827" + "startPosition": "3847" }, { - "endPosition": "3839", + "endPosition": "3859", "kind": "NULL_LITERAL", - "startPosition": "3835" + "startPosition": "3855" } ], - "startPosition": "3792" + "startPosition": "3812" } }, { "expression": { - "endPosition": "3882", + "endPosition": "3902", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3851", + "endPosition": "3871", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3846" + "startPosition": "3866" }, "arguments": [ { - "endPosition": "3881", + "endPosition": "3901", "kind": "FUNCTION_INVOCATION", "functionSelect": { "identifier": "stringify", "expression": { - "endPosition": "3856", + "endPosition": "3876", "kind": "IDENTIFIER", "name": "JSON", - "startPosition": "3852" + "startPosition": "3872" }, - "endPosition": "3866", + "endPosition": "3886", "kind": "MEMBER_SELECT", - "startPosition": "3852" + "startPosition": "3872" }, "arguments": [ { - "endPosition": "3871", + "endPosition": "3891", "kind": "IDENTIFIER", "name": "tree", - "startPosition": "3867" + "startPosition": "3887" }, { - "endPosition": "3877", + "endPosition": "3897", "kind": "NULL_LITERAL", - "startPosition": "3873" + "startPosition": "3893" }, { - "endPosition": "3880", + "endPosition": "3900", "kind": "NUMBER_LITERAL", "value": "2", - "startPosition": "3879" + "startPosition": "3899" } ], - "startPosition": "3852" + "startPosition": "3872" } ], - "startPosition": "3846" + "startPosition": "3866" }, - "endPosition": "3882", + "endPosition": "3902", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3846" + "startPosition": "3866" }, { "expression": { - "endPosition": "3898", + "endPosition": "3918", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3893", + "endPosition": "3913", "kind": "IDENTIFIER", "name": "print", - "startPosition": "3888" + "startPosition": "3908" }, "arguments": [ { - "endPosition": "3896", + "endPosition": "3916", "kind": "STRING_LITERAL", "value": "]", - "startPosition": "3895" + "startPosition": "3915" } ], - "startPosition": "3888" + "startPosition": "3908" }, - "endPosition": "3898", + "endPosition": "3918", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3888" + "startPosition": "3908" } ], - "startPosition": "3615" + "startPosition": "3635" }, "strict": "false", - "startPosition": "3599", + "startPosition": "3619", "parameters": [] }, { "expression": { - "endPosition": "3909", + "endPosition": "3929", "kind": "FUNCTION_INVOCATION", "functionSelect": { - "endPosition": "3907", + "endPosition": "3927", "kind": "IDENTIFIER", "name": "main", - "startPosition": "3903" + "startPosition": "3923" }, "arguments": [], - "startPosition": "3903" - }, - "endPosition": "3909", + "startPosition": "3923" + }, + "endPosition": "3929", "kind": "EXPRESSION_STATEMENT", - "startPosition": "3903" + "startPosition": "3923" } ], "sourceName": "parserapi.js", "strict": "false", "startPosition": "1136" -} -] +} +] diff -r d47c58140b41 -r 427f83353f73 nashorn/test/script/nosecurity/treeapi/utils.js --- a/nashorn/test/script/nosecurity/treeapi/utils.js Tue Mar 31 16:22:59 2015 -0700 +++ b/nashorn/test/script/nosecurity/treeapi/utils.js Mon Apr 06 10:35:43 2015 -0700 @@ -78,5 +78,5 @@ var tree = parser.create(args).parse("test.js", code, function (message) { messages.push(convert(message)) }) - print(JSON.stringify(messages, null, 2)) + print(JSON.stringify(messages, null, 2).replace(/\\r/g, '')) } \ No newline at end of file